[v4] Bottom Sheet getting snapped to -1 (closed state) in certain situations with dynamic snap points #1053
Open
Description
Bug
I'm working in a project that has a bottom sheet with 2 dynamic snapPoints (minimised, medium), when these are quickly changing, the bottom sheet snaps to -1 (closed state) and doesn't snap back.
I observed that this issue mostly happens, if in one of these changes, the snapPoints aren't ascending.
Video with sample code
Screen.Recording.2022-08-05.at.18.55.06.mov
Environment info
Library | Version |
---|---|
@gorhom/bottom-sheet | 4.2.2 |
react-native | 0.68.2 |
react-native-reanimated | 2.6.0 |
react-native-gesture-handler | 2.3.2 |
Steps To Reproduce
- Bottom sheet needs to have 2 dynamic snapPoints
- SnapPoints need to be quickly changing.
- At some point snapPoints need to be in descending order
Use sample code provided bellow to reproduce this issue.
Describe what you expected to happen:
animatedIndex
snaps to -1- Bottom sheet disappears and doesn't snap back
Reproducible sample code
import React, { useMemo, useRef } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import BottomSheet from '@gorhom/bottom-sheet';
import { useSharedValue } from 'react-native-reanimated';
function generateRandomInt(min: number, max: number) {
return Math.floor(Math.random() * (max - min) + min);
}
const useSimulateDynamicSnapPoints = () => {
const [now, setNow] = React.useState(0);
React.useEffect(() => {
const interval = setInterval(() => {
setNow(Date.now());
}, 1);
return () => {
clearInterval(interval);
};
}, []);
const snapPoints = useMemo(() => {
const snapPointsNotAscending = [
generateRandomInt(200, 250),
generateRandomInt(100, 200),
];
const snapPointsAscending = [
generateRandomInt(100, 200),
generateRandomInt(200, 250),
];
if (Date.now() % 2 !== 0) {
return snapPointsNotAscending;
}
return snapPointsAscending;
}, [now]);
return snapPoints;
};
const App = () => {
const bottomSheetRef = useRef<BottomSheet>(null);
const animatedIndex = useSharedValue(0);
const snapPoints = useSimulateDynamicSnapPoints();
console.log(`
SNAP_POINTS ---> ${snapPoints}
ANIMATED_INDEX ---> ${animatedIndex.value}`);
return (
<View style={styles.container}>
<BottomSheet
ref={bottomSheetRef}
index={1}
snapPoints={snapPoints}
animatedIndex={animatedIndex}
>
<View>
<Text>I'm visible, please don't disappear 🙏🏽🙏🏽🙏🏽 </Text>
</View>
</BottomSheet>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'grey',
},
});
export default App;