Skip to content

Commit 101456a

Browse files
committed
fix: refactoring logic of withAutoFillData, Add onProgressChange value boundary
fix #158
1 parent 4076edb commit 101456a

File tree

4 files changed

+127
-34
lines changed

4 files changed

+127
-34
lines changed

src/Carousel.tsx

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ import { useVisibleRanges } from './hooks/useVisibleRanges';
99

1010
import type { ICarouselInstance, TCarouselProps } from './types';
1111
import { StyleSheet, View } from 'react-native';
12-
import { DATA_LENGTH } from './constants';
1312
import { BaseLayout } from './layouts/BaseLayout';
1413
import { useLayoutConfig } from './hooks/useLayoutConfig';
1514
import { useInitProps } from './hooks/useInitProps';
1615
import { CTX } from './store';
1716
import { useCommonVariables } from './hooks/useCommonVariables';
1817
import { useOnProgressChange } from './hooks/useOnProgressChange';
18+
import { computedRealIndexWithAutoFillData } from './utils/computedWithAutoFillData';
1919

2020
const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
2121
(_props, ref) => {
@@ -25,6 +25,7 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
2525
data,
2626
rawData,
2727
loop,
28+
autoFillData,
2829
mode,
2930
style,
3031
width,
@@ -60,7 +61,14 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
6061
}, [loop, size, dataLength]);
6162

6263
usePropsErrorBoundary(props);
63-
useOnProgressChange({ size, offsetX, rawData, onProgressChange });
64+
useOnProgressChange({
65+
autoFillData,
66+
loop,
67+
size,
68+
offsetX,
69+
rawData,
70+
onProgressChange,
71+
});
6472

6573
const carouselController = useCarouselController({
6674
loop,
@@ -148,14 +156,12 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
148156

149157
const renderLayout = React.useCallback(
150158
(item: any, i: number) => {
151-
let realIndex = i;
152-
if (rawData.length === DATA_LENGTH.SINGLE_ITEM) {
153-
realIndex = i % 1;
154-
}
155-
156-
if (rawData.length === DATA_LENGTH.DOUBLE_ITEM) {
157-
realIndex = i % 2;
158-
}
159+
const realIndex = computedRealIndexWithAutoFillData({
160+
index: i,
161+
dataLength: rawData.length,
162+
loop,
163+
autoFillData,
164+
});
159165

160166
return (
161167
<BaseLayout
@@ -176,9 +182,11 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
176182
);
177183
},
178184
[
185+
loop,
179186
rawData,
180187
offsetX,
181188
visibleRanges,
189+
autoFillData,
182190
renderItem,
183191
layoutConfig,
184192
customAnimation,

src/hooks/useInitProps.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import { computedFillDataWithAutoFillData } from '@/utils/computedWithAutoFillData';
12
import React from 'react';
2-
import { DATA_LENGTH } from '../constants';
33
import type { TCarouselProps } from '../types';
44

55
type TGetRequiredProps<P extends keyof TCarouselProps> = Record<
@@ -15,6 +15,7 @@ export type TInitializeCarouselProps<T> = TCarouselProps<T> &
1515
| 'height'
1616
| 'scrollAnimationDuration'
1717
| 'autoPlayInterval'
18+
| 'autoFillData'
1819
> & {
1920
// Raw data that has not been processed
2021
rawData: T[];
@@ -43,19 +44,16 @@ export function useInitProps<T>(
4344
const height = Math.round(_height || 0);
4445
const autoPlayInterval = Math.max(_autoPlayInterval, 0);
4546

46-
const data = React.useMemo<T[]>(() => {
47-
if (!loop || !autoFillData) return rawData;
48-
49-
if (rawData.length === DATA_LENGTH.SINGLE_ITEM) {
50-
return [rawData[0], rawData[0], rawData[0]];
51-
}
52-
53-
if (rawData.length === DATA_LENGTH.DOUBLE_ITEM) {
54-
return [rawData[0], rawData[1], rawData[0], rawData[1]];
55-
}
56-
57-
return rawData;
58-
}, [rawData, loop, autoFillData]);
47+
const data = React.useMemo<T[]>(
48+
() =>
49+
computedFillDataWithAutoFillData<T>({
50+
loop,
51+
autoFillData,
52+
data: rawData,
53+
dataLength: rawData.length,
54+
}),
55+
[rawData, loop, autoFillData]
56+
);
5957

6058
if (props.mode === 'vertical-stack' || props.mode === 'horizontal-stack') {
6159
if (!props.modeConfig) {
@@ -67,6 +65,7 @@ export function useInitProps<T>(
6765
return {
6866
...props,
6967
defaultIndex,
68+
autoFillData,
7069
data,
7170
rawData,
7271
loop,

src/hooks/useOnProgressChange.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,39 @@ import Animated, {
22
runOnJS,
33
useAnimatedReaction,
44
} from 'react-native-reanimated';
5-
import { DATA_LENGTH } from '../constants';
5+
import { computedOffsetXValueWithAutoFillData } from '@/utils/computedWithAutoFillData';
66
import type { TCarouselProps } from '../types';
77

88
export function useOnProgressChange(
99
opts: {
1010
size: number;
11+
autoFillData: boolean;
12+
loop: boolean;
1113
offsetX: Animated.SharedValue<number>;
1214
rawData: TCarouselProps['data'];
1315
} & Pick<TCarouselProps, 'onProgressChange'>
1416
) {
15-
const { offsetX, rawData, size, onProgressChange } = opts;
17+
const { autoFillData, loop, offsetX, rawData, size, onProgressChange } =
18+
opts;
19+
1620
const rawDataLength = rawData.length;
21+
1722
useAnimatedReaction(
1823
() => offsetX.value,
1924
(_value) => {
20-
let value = _value;
21-
22-
if (rawDataLength === DATA_LENGTH.SINGLE_ITEM) {
23-
value = value % size;
24-
}
25+
let value = computedOffsetXValueWithAutoFillData({
26+
value: _value,
27+
rawDataLength,
28+
size,
29+
autoFillData,
30+
loop,
31+
});
2532

26-
if (rawDataLength === DATA_LENGTH.DOUBLE_ITEM) {
27-
value = value % (size * 2);
33+
if (!loop) {
34+
value = Math.max(
35+
-((rawDataLength - 1) * size),
36+
Math.min(value, 0)
37+
);
2838
}
2939

3040
let absoluteProgress = Math.abs(value / size);
@@ -36,6 +46,6 @@ export function useOnProgressChange(
3646
!!onProgressChange &&
3747
runOnJS(onProgressChange)(value, absoluteProgress);
3848
},
39-
[onProgressChange, rawDataLength]
49+
[loop, autoFillData, rawDataLength, onProgressChange]
4050
);
4151
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { DATA_LENGTH } from 'src/constants';
2+
3+
const { SINGLE_ITEM, DOUBLE_ITEM } = DATA_LENGTH;
4+
5+
function isAutoFillData(params: { autoFillData: boolean; loop: boolean }) {
6+
'worklet';
7+
return !!params.loop && !!params.autoFillData;
8+
}
9+
10+
type BaseParams<T extends object = {}> = {
11+
autoFillData: boolean;
12+
loop: boolean;
13+
} & T;
14+
15+
export function computedOffsetXValueWithAutoFillData(
16+
params: BaseParams<{
17+
rawDataLength: number;
18+
value: number;
19+
size: number;
20+
}>
21+
) {
22+
'worklet';
23+
24+
const { rawDataLength, value, size, loop, autoFillData } = params;
25+
26+
if (isAutoFillData({ loop, autoFillData })) {
27+
switch (rawDataLength) {
28+
case SINGLE_ITEM:
29+
return value % size;
30+
case DOUBLE_ITEM:
31+
return value % (size * 2);
32+
}
33+
}
34+
35+
return value;
36+
}
37+
38+
export function computedRealIndexWithAutoFillData(
39+
params: BaseParams<{
40+
index: number;
41+
dataLength: number;
42+
}>
43+
) {
44+
const { index, dataLength, loop, autoFillData } = params;
45+
46+
if (isAutoFillData({ loop, autoFillData })) {
47+
switch (dataLength) {
48+
case SINGLE_ITEM:
49+
return index % 1;
50+
case DOUBLE_ITEM:
51+
return index % 2;
52+
}
53+
}
54+
55+
return index;
56+
}
57+
58+
export function computedFillDataWithAutoFillData<T>(
59+
params: BaseParams<{
60+
data: T[];
61+
dataLength: number;
62+
}>
63+
): T[] {
64+
const { data, loop, autoFillData, dataLength } = params;
65+
66+
if (isAutoFillData({ loop, autoFillData })) {
67+
switch (dataLength) {
68+
case SINGLE_ITEM:
69+
return [data[0], data[0], data[0]];
70+
case DOUBLE_ITEM:
71+
return [data[0], data[1], data[0], data[1]];
72+
}
73+
}
74+
75+
return data;
76+
}

0 commit comments

Comments
 (0)