Skip to content

Commit dbd6983

Browse files
authored
chore: added useReactiveValue/s (#65)
* chore: added useReactiveVlaue/s * chore: updated basic example
1 parent fd82d9f commit dbd6983

File tree

6 files changed

+96
-118
lines changed

6 files changed

+96
-118
lines changed

example/ios/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,4 +481,4 @@ SPEC CHECKSUMS:
481481

482482
PODFILE CHECKSUM: aff15ad1e9bd5c910cdc2b575487ce8c56864ae7
483483

484-
COCOAPODS: 1.9.1
484+
COCOAPODS: 1.9.3

example/src/screens/static/BasicExample.tsx

Lines changed: 19 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,32 @@
11
import React, { useCallback, useMemo, useRef, useState } from 'react';
22
import { View, StyleSheet } from 'react-native';
3-
import { useHeaderHeight } from '@react-navigation/stack';
4-
import Animated, {
5-
interpolate,
6-
concat,
7-
Extrapolate,
8-
} from 'react-native-reanimated';
3+
import { concat } from 'react-native-reanimated';
94
import { ReText, useValue } from 'react-native-redash';
10-
import BottomSheet, { BottomSheetFlatList } from '@gorhom/bottom-sheet';
11-
import Handle from '../../components/handle';
5+
import BottomSheet from '@gorhom/bottom-sheet';
126
import Button from '../../components/button';
7+
import ContactList from '../../components/contactList';
8+
import { useSafeArea } from 'react-native-safe-area-context';
139

1410
const BasicExample = () => {
1511
// state
1612
const [enabled, setEnabled] = useState(true);
13+
const [dynamicSnapPoint, setDynamicSnapPoint] = useState(450);
1714

1815
// hooks
1916
const bottomSheetRef = useRef<BottomSheet>(null);
20-
const headerHeight = useHeaderHeight();
17+
const { top: topSafeArea } = useSafeArea();
2118

2219
// variables
23-
const snapPoints = useMemo(() => [150, 300, 450], []);
20+
const snapPoints = useMemo(() => [150, dynamicSnapPoint], [dynamicSnapPoint]);
2421
const position = useValue<number>(0);
2522

2623
// styles
27-
const shadowOverlayStyle = useMemo(
24+
const containerStyle = useMemo(
2825
() => ({
29-
...styles.shadowOverlay,
30-
opacity: interpolate(position, {
31-
inputRange: [300, 450],
32-
outputRange: [0, 1],
33-
extrapolate: Extrapolate.CLAMP,
34-
}),
26+
...styles.container,
27+
paddingTop: topSafeArea,
3528
}),
36-
// eslint-disable-next-line react-hooks/exhaustive-deps
37-
[]
29+
[topSafeArea]
3830
);
3931

4032
// callbacks
@@ -44,31 +36,20 @@ const BasicExample = () => {
4436
const handleSnapPress = useCallback(index => {
4537
bottomSheetRef.current?.snapTo(index);
4638
}, []);
47-
4839
const handleClosePress = useCallback(() => {
4940
bottomSheetRef.current?.close();
5041
}, []);
42+
const handleIncreaseDynamicSnapPoint = useCallback(() => {
43+
setDynamicSnapPoint(state => state + 50);
44+
}, []);
5145

5246
// renders
53-
// const renderHeader = useCallback(() => {
54-
// return (
55-
// <View style={styles.headerContainer}>
56-
// <Text style={styles.title}>Basic Screen</Text>
57-
// </View>
58-
// );
59-
// }, []);
60-
6147
return (
62-
<View style={styles.container}>
63-
<Button
64-
label="Snap To 450"
65-
style={styles.buttonContainer}
66-
onPress={() => handleSnapPress(2)}
67-
/>
48+
<View style={containerStyle}>
6849
<Button
69-
label="Snap To 300"
50+
label="Increase Dynamic Snap Point"
7051
style={styles.buttonContainer}
71-
onPress={() => handleSnapPress(1)}
52+
onPress={handleIncreaseDynamicSnapPoint}
7253
/>
7354
<Button
7455
label="Snap To 150"
@@ -87,92 +68,16 @@ const BasicExample = () => {
8768
onPress={() => setEnabled(state => !state)}
8869
/>
8970
<ReText text={concat('Position from bottom: ', position)} />
90-
<Animated.View pointerEvents="none" style={shadowOverlayStyle} />
9171
<BottomSheet
9272
ref={bottomSheetRef}
9373
enabled={enabled}
9474
snapPoints={snapPoints}
9575
initialSnapIndex={1}
96-
handleComponent={Handle}
97-
topInset={headerHeight}
76+
topInset={topSafeArea}
9877
animatedPosition={position}
9978
onChange={handleSheetChanges}
10079
>
101-
{/* <View
102-
style={{
103-
position: 'absolute',
104-
left: 0,
105-
right: 0,
106-
height: (25 * sheetHeight) / 100,
107-
backgroundColor: 'rgba(0,0,0,0.25)',
108-
}}
109-
/>
110-
<View
111-
style={{
112-
position: 'absolute',
113-
left: 0,
114-
right: 0,
115-
height: (50 * sheetHeight) / 100,
116-
backgroundColor: 'rgba(0,0,0,0.50)',
117-
}}
118-
/>
119-
<View
120-
style={{
121-
position: 'absolute',
122-
left: windowWidth / 2 - 25,
123-
width: 50,
124-
height: 10,
125-
backgroundColor: 'red',
126-
}}
127-
/>
128-
<View
129-
style={{
130-
position: 'absolute',
131-
left: windowWidth / 2 - 25,
132-
bottom: 0,
133-
width: 50,
134-
height: 10,
135-
backgroundColor: 'red',
136-
}}
137-
/>
138-
<View
139-
style={{
140-
position: 'absolute',
141-
bottom: sheetHeight / 2 - 25,
142-
width: 10,
143-
height: 50,
144-
backgroundColor: 'red',
145-
}}
146-
/>
147-
148-
<View
149-
style={{
150-
position: 'absolute',
151-
bottom: sheetHeight / 2 - 25,
152-
right: 0,
153-
width: 10,
154-
height: 50,
155-
backgroundColor: 'red',
156-
}}
157-
/> */}
158-
159-
{/* <Button
160-
label="Open"
161-
style={styles.buttonContainer}
162-
onPress={() => handleSnapPress(1)}
163-
/> */}
164-
{/* <ContactList type="ScrollView" header={renderHeader} /> */}
165-
<View style={{ height: 100, backgroundColor: 'blue' }} />
166-
<BottomSheetFlatList
167-
contentContainerStyle={{ flexGrow: 1, backgroundColor: '#fff' }}
168-
data={[0, 1, 2, 3, 4, 5, 6, 7, 8]}
169-
renderItem={() => (
170-
<View
171-
style={{ backgroundColor: 'red', height: 100, marginBottom: 20 }}
172-
/>
173-
)}
174-
/>
175-
<View style={{ height: 100, backgroundColor: 'green' }} />
80+
<ContactList type="View" />
17681
</BottomSheet>
17782
</View>
17883
);

src/components/bottomSheet/useTransition.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { State } from 'react-native-gesture-handler';
2323
import { useClock, useValue, snapPoint } from 'react-native-redash';
2424
import type { BottomSheetAnimationConfigs } from './types';
2525
import { GESTURE } from '../../constants';
26+
import { useReactiveValue, useReactiveValues } from '../../hooks';
2627

2728
interface TransitionProps extends Required<BottomSheetAnimationConfigs> {
2829
contentPanGestureState: Animated.Value<State>;
@@ -48,11 +49,12 @@ export const useTransition = ({
4849
handlePanGestureTranslationY,
4950
handlePanGestureVelocityY,
5051
scrollableContentOffsetY,
51-
snapPoints,
52+
snapPoints: _snapPoints,
5253
initialPosition,
5354
}: TransitionProps) => {
5455
const currentGesture = useValue<GESTURE>(GESTURE.UNDETERMINED);
55-
const currentPosition = useValue(initialPosition);
56+
const currentPosition = useReactiveValue(initialPosition);
57+
const snapPoints = useReactiveValues(_snapPoints);
5658

5759
const isPanningContent = useMemo(
5860
() => eq(contentPanGestureState, State.ACTIVE),
@@ -86,11 +88,13 @@ export const useTransition = ({
8688
frameTime: new Animated.Value(0),
8789
time: new Animated.Value(0),
8890
}),
89-
[initialPosition]
91+
// eslint-disable-next-line react-hooks/exhaustive-deps
92+
[]
9093
);
9194

9295
const finishTiming = useMemo(
9396
() => [
97+
// debug('finish timing', config.toValue),
9498
set(currentGesture, GESTURE.UNDETERMINED),
9599
set(shouldAnimate, 0),
96100
set(currentPosition, config.toValue),

src/hooks/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ export { useBottomSheetInternal } from './useBottomSheetInternal';
22
export { useScrollable } from './useScrollable';
33
export { useScrollableInternal } from './useScrollableInternal';
44
export { useStableCallback } from './useStableCallback';
5+
export { useReactiveValue } from './useReactiveValue';
6+
export { useReactiveValues } from './useReactiveValues';

src/hooks/useReactiveValue.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { useEffect, useRef } from 'react';
2+
import Animated from 'react-native-reanimated';
3+
4+
export const useReactiveValue = (value: number) => {
5+
// ref
6+
const ref = useRef<Animated.Value<number>>(null);
7+
if (ref.current === null) {
8+
// @ts-ignore
9+
ref.current = new Animated.Value(value);
10+
}
11+
12+
// effects
13+
useEffect(() => {
14+
if (ref.current) {
15+
ref.current.setValue(value);
16+
}
17+
}, [value]);
18+
19+
return ref.current;
20+
};

src/hooks/useReactiveValues.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { useEffect, useRef } from 'react';
2+
import Animated from 'react-native-reanimated';
3+
4+
export const useReactiveValues = (values: number[]) => {
5+
// ref
6+
const ref = useRef<Animated.Value<number>[]>(null);
7+
if (ref.current === null) {
8+
// @ts-ignore
9+
ref.current = [];
10+
values.map(value => {
11+
// @ts-ignore
12+
ref.current.push(new Animated.Value(value));
13+
});
14+
}
15+
16+
// effects
17+
useEffect(() => {
18+
if (ref.current) {
19+
values.map((value, index) => {
20+
// @ts-ignore
21+
if (ref.current[index]) {
22+
// update current value
23+
// @ts-ignore
24+
ref.current[index].setValue(value);
25+
} else {
26+
// insert current value
27+
// @ts-ignore
28+
ref.current.push(new Animated.Value(value));
29+
}
30+
});
31+
32+
/**
33+
* if previous animated array has more values than the updated
34+
* array, we will need to set the extra values to the last
35+
* value of the updated array.
36+
*/
37+
if (values.length < ref.current.length) {
38+
const lastValue = values[values.length - 1];
39+
for (let i = values.length - 1; i <= ref.current.length - 1; i++) {
40+
ref.current[i].setValue(lastValue);
41+
}
42+
}
43+
}
44+
}, [values]);
45+
46+
return ref.current!;
47+
};

0 commit comments

Comments
 (0)