[Bug]: BottomSheetFlashList doesn't respond to scrolling in `v5.1.5+`
Version
v5
Reanimated Version
v3
Gesture Handler Version
v2
Platforms
Android
What happened?
When using BottomSheetFlashList, the scroll view doesn't respond to scrolling.
Reproduction steps
(The template https://snack.expo.dev/@gorhom/bottom-sheet---issue-reproduction-template didn't work for me. There was some issue with peer dependencies on @types/* packages, but it couldn't install them)
- Make sure
"@gorhom/bottom-sheet": "5.1.4"in package.json bun ibunx expo run:androidorbunx expo run:ios
Scrolling works
- Upgrade to
"@gorhom/bottom-sheet": "5.1.5"or"@gorhom/bottom-sheet": "5.1.6"in package.json bun ibunx expo run:androidorbunx expo run:ios
Scrolling no longer works
Reproduction sample
https://github.com/AlexanderHott/gorhom-bottom-sheet-no-scroll
Relevant log output
It somehow seems to work in the examples directory of the project. I got it to compile locally, and that works. However, installing from the master branch on my example above doesn't work.
"@gorhom/bottom-sheet": "git+https://github.com/gorhom/react-native-bottom-sheet.git#master",
Am I missing something from the examples?
Same for me with SectionList, I'm unable to scroll when I update to v5 (v4 is working correctly)
+1
I can't either.
Hey 👋 I can confirm that I experience the same scrolling issues on flashlists in 5.1.6 as well as sizing issues when embedded in bottom sheets.
WARN FlashList's rendered size is not usable. Either the height or width is too small (<2px). Please make sure that the parent view of the list has a valid size. FlashList will match the size of the parent.
This is making my lists not visible anymore in those sheets and I do appreciate that even though this is a flashlist warning I can confirm that I did not have nor the warning nor the sheet visibility issue in 5.1.5.
It probably comes from this commit, no? https://github.com/gorhom/react-native-bottom-sheet/commit/53974786a18aceab1cc15def1b29c94ef93002e3 - hope it helps 🙏
The problem basically being that the underlying native ScrollView is set to the height of the content. When the scrollview's size is equal to the content size there is nothing to scroll, thus no scroll will happen.
As you can see here the layout height is 2105, which is equal to the content height:
This seems to be a bug with react-native's yoga layout calculation. However, as it was working before, it must be something specific to the view hierarchy changes that happened in this commit:
- https://github.com/gorhom/react-native-bottom-sheet/commit/209886dc8ec0d5c19c7d2b72226ec54cf178000c
One way to fix this: is to supply a maxHeight to the scroll view like component, or to the parent rendering it. This limits the height for the yoga layout calculations.
It probably comes from this commit, no? https://github.com/gorhom/react-native-bottom-sheet/commit/53974786a18aceab1cc15def1b29c94ef93002e3 - hope it helps 🙏
I also saw some other kind of bugs with that commit's changes. In general it seems like mixing flex and absolute layout can bring yoga into a position where it calculates wrong values.
+1
Same here. Though the issue is specific to Android in my case.
Same issue for me.. Anyone can help me here.
Same issue here
Any updates?
Any updates?
Downgrade to "@gorhom/bottom-sheet": "4.6.4" worked for me and use the FlatList that comes with react-native-gesture-handler
import { FlatList } from "react-native-gesture-handler";
Remove BottomSheetView if it's been used as it's not neccessary in this version
remove GestureDetector and Gesture
"@gorhom/bottom-sheet": "^5.1.1"
previous code
// *Library Imports import React from 'react'; import { View, StyleSheet, FlatList } from 'react-native'; import { Text } from 'react-native-paper'; import Feather from 'react-native-vector-icons/Feather'; import { Gesture, GestureDetector } from 'react-native-gesture-handler'; import { useTranslation } from 'react-i18next';
// *Local IMports import { screenHeight } from '../../config/dimensions';
export default SectionWrapper = ({ children, data = [], renderItem, showAction = false, onPressAction = () => { }, horizontal = true, title = "", refresh, ...props }) => {
const nativeGesture = Gesture.Native();
const { t } = useTranslation();
return (
<View>
{title &&
<View style={styles.Header} >
<Text variant={'titleMedium'} style={{ fontFamily: 'Poppins-Regular' }}>{t(title)}</Text>
{showAction && <Feather name={'arrow-right'} onPress={onPressAction} size={20} />}
</View>
}
<GestureDetector gesture={nativeGesture}>
<FlatList
data={data}
renderItem={renderItem}
horizontal={horizontal}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
keyExtractor={(item, index) => item?.id?.toString?.() || index.toString()}
{...props}
onRefresh={refresh}
refreshing={false}
initialNumToRender={10}
maxToRenderPerBatch={5}
windowSize={10}
removeClippedSubviews={true}
getItemLayout={props.getItemLayout}
/>
</GestureDetector>
</View>
);
};
const styles = StyleSheet.create({ Header: { width: '100%', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 0.015 * screenHeight, marginLeft: 0.01 * screenHeight, elevation: 4 } })
updated code
// *Library Imports import React from 'react'; import { View, StyleSheet } from 'react-native'; import { FlatList } from 'react-native-gesture-handler'; import { Text } from 'react-native-paper'; import Feather from 'react-native-vector-icons/Feather'; import { useTranslation } from 'react-i18next';
// *Local IMports import { screenHeight } from '../../config/dimensions';
export default SectionWrapper = ({ children, data = [], renderItem, showAction = false, onPressAction = () => { }, horizontal = true, title = "", refresh, ...props }) => {
const { t } = useTranslation();
return (
<View>
{title &&
<View style={styles.Header} >
<Text variant={'titleMedium'} style={{ fontFamily: 'Poppins-Regular' }}>{t(title)}</Text>
{showAction && <Feather name={'arrow-right'} onPress={onPressAction} size={20} />}
</View>
}
<FlatList
data={data}
renderItem={renderItem}
horizontal={horizontal}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
keyExtractor={(item, index) => item?.id?.toString?.() || index.toString()}
{...props}
onRefresh={refresh}
refreshing={false}
initialNumToRender={10}
maxToRenderPerBatch={5}
windowSize={10}
removeClippedSubviews={true}
getItemLayout={props.getItemLayout}
simultaneousHandlers={props.simultaneousHandlers}
waitFor={props.waitFor}
/>
</View>
);
};
const styles = StyleSheet.create({ Header: { width: '100%', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 0.015 * screenHeight, marginLeft: 0.01 * screenHeight, elevation: 4 } })
Do you confirm this is not fixed in 5.1.8 please? Thanks 🙌
I have the same problem, using FlashList and FlatList, only using ScrollView and then mapping over the items was I able to solve the problem, I know mapping over items in react-native is bad, does anyone have a better solution?
I updated to 5.1.8 and I seem to have the same issue.
Here is what I have noticed though. I have a FlashList in a BottomSheetView in a BottomSheetModal.
In development:
- Opening the BottomSheetModal
- You can't scroll
- Replacing the BottomSheetView with a plain react-native <View> & hot reloading
- You can scroll
However, if you keep using a plain View instead of the BottomSheetView, then the BottomSheetModal doesn't open at all...
Here's my ugly hack:
const content = <BottomSheetFlashList
estimatedItemSize={ESTIMATED_LIST_HEIGHT}
showsVerticalScrollIndicator={false}
data={[0]}
renderItem={() => <FlashList
scrollEnabled={false}
{...otherFlashListProps} />
}
/>
const [isMounted, setMounted] = useState(false)
return (
isMounted
? <View style={{ flex: 1 }}>
{content}
</View>
: <BottomSheetView style={{ flex: 1 }} onLayout={() => {
setMounted(true)
}}>
{content}
</BottomSheetView>
)
I'm using BottomSheetScrollView and encountered this issue.
Wrapping it with <NativeViewGestureHandler disallowInterruption={true}> is fixing the issue.
I know is deprecated, but, using <GestureDetector gesture={nativeGesture}> is not working.
I use version 5.2.5, The flashlist example doesn't work: https://gorhom.dev/react-native-bottom-sheet/components/bottomsheetflashlist Instead, I use React Native Bottom Sheet Modal. The code below with BottomSheetFlashList works for me:
import {
BottomSheetFlashList,
BottomSheetModal,
BottomSheetModalProvider,
} from "@gorhom/bottom-sheet";
import React, { useCallback, useMemo, useRef } from "react";
import { Text, TouchableOpacity, View } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
const Playground = () => {
const bottomSheetModalRef = useRef<BottomSheetModal>(null);
const renderItem = useCallback(({ item }) => {
return (
<View key={item}>
<Text>{item}</Text>
</View>
);
}, []);
const data = useMemo(
() =>
Array(1000)
.fill(0)
.map((_, index) => `index-${index}`),
[]
);
const handleLocationBoxOnPress = () => {
bottomSheetModalRef.current?.present();
bottomSheetModalRef.current?.snapToIndex(1);
};
return (
<GestureHandlerRootView>
<TouchableOpacity onPress={handleLocationBoxOnPress}>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
</TouchableOpacity>
<BottomSheetModalProvider>
<BottomSheetModal
ref={bottomSheetModalRef}
index={1}
snapPoints={["50%", "100%"]}
enableDynamicSizing={false}
enableDismissOnClose={true}
enableOverDrag={false}
overDragResistanceFactor={100}
>
<BottomSheetFlashList
data={data}
keyExtractor={(item) => item}
renderItem={renderItem}
keyboardShouldPersistTaps="handled"
/>
</BottomSheetModal>
</BottomSheetModalProvider>
</GestureHandlerRootView>
);
};
export default Playground;
or you may use the useBottomSheetScrollableCreator, still works for me:
import {
BottomSheetFlashList,
BottomSheetModal,
BottomSheetModalProvider,
useBottomSheetScrollableCreator,
} from "@gorhom/bottom-sheet";
import { FlashList } from "@shopify/flash-list";
import React, { useCallback, useMemo, useRef } from "react";
import { Text, TouchableOpacity, View } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
const Playground = () => {
const bottomSheetModalRef = useRef<BottomSheetModal>(null);
const renderItem = useCallback(({ item }) => {
return (
<View key={item}>
<Text>{item}</Text>
</View>
);
}, []);
const data = useMemo(
() =>
Array(1000)
.fill(0)
.map((_, index) => `index-${index}`),
[]
);
const handleLocationBoxOnPress = () => {
bottomSheetModalRef.current?.present();
bottomSheetModalRef.current?.snapToIndex(1);
};
const BottomSheetScrollable = useBottomSheetScrollableCreator();
return (
<GestureHandlerRootView>
<TouchableOpacity onPress={handleLocationBoxOnPress}>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
<Text>Click Me!</Text>
</TouchableOpacity>
<BottomSheetModalProvider>
<BottomSheetModal
ref={bottomSheetModalRef}
index={1}
snapPoints={["50%", "90%"]}
enableDynamicSizing={false}
enableDismissOnClose={true}
enableOverDrag={false}
overDragResistanceFactor={100}
>
<FlashList
data={data}
keyExtractor={(item) => item}
renderItem={renderItem}
keyboardShouldPersistTaps="handled"
renderScrollComponent={BottomSheetScrollable}
/>
</BottomSheetModal>
</BottomSheetModalProvider>
</GestureHandlerRootView>
);
};
export default Playground;
@gorhom any update on this?
Same issue in v5.2.6
I have tried using useBottomSheetScrollableCreator() but it does not work
@gorhom Any workaround on this?
In my case scroll didn't work because the BottomSheetFlashList was wrapped into BottomSheetView
Check the order of components
The true order is
<GestureHandlerRootView style={StyleSheet.absoluteFill}>
<BottomSheet
ref={bsRef}
enablePanDownToClose={true}
enableOverDrag={false}
keyboardInputMode={'adjustNothing'}
>
<BottomSheetFlashList
contentContainerStyle={styles.contentContainer}
data={data}
/>
</BottomSheet>
</GestureHandlerRootView>
Also BottomSheetFlashList's contentContainerStyle mustn't contain style flex: 1
In my case scroll didn't work because the
BottomSheetFlashListwas wrapped intoBottomSheetViewCheck the order of components The true order is<GestureHandlerRootView style={StyleSheet.absoluteFill}> <BottomSheet ref={bsRef} enablePanDownToClose={true} enableOverDrag={false} keyboardInputMode={'adjustNothing'} > <BottomSheetFlashList contentContainerStyle={styles.contentContainer} data={data} /> </BottomSheet> </GestureHandlerRootView>Also BottomSheetFlashList's
contentContainerStylemustn't contain styleflex: 1
Thank you. After removing BottomSheetView, I can scroll the Flatlist again
In my case scroll didn't work because the
BottomSheetFlashListwas wrapped intoBottomSheetViewCheck the order of components The true order is<GestureHandlerRootView style={StyleSheet.absoluteFill}> <BottomSheet ref={bsRef} enablePanDownToClose={true} enableOverDrag={false} keyboardInputMode={'adjustNothing'} > <BottomSheetFlashList contentContainerStyle={styles.contentContainer} data={data} /> </BottomSheet> </GestureHandlerRootView>Also BottomSheetFlashList's
contentContainerStylemustn't contain styleflex: 1
I can confirm that this solution solves the problem, but what if you still want a BottomSheetView with a FlashList below it?
In my case scroll didn't work because the
BottomSheetFlashListwas wrapped intoBottomSheetViewCheck the order of components The true order is<GestureHandlerRootView style={StyleSheet.absoluteFill}> <BottomSheet ref={bsRef} enablePanDownToClose={true} enableOverDrag={false} keyboardInputMode={'adjustNothing'} > <BottomSheetFlashList contentContainerStyle={styles.contentContainer} data={data} /> </BottomSheet> </GestureHandlerRootView>Also BottomSheetFlashList's
contentContainerStylemustn't contain styleflex: 1I can confirm that this solution solves the problem, but what if you still want a
BottomSheetViewwith aFlashListbelow it?
I have one component with such structure:
<BottomSheet ...>
<View ... /> // <--- usual react native's view
<BottomSheetFlashList ... />
</BottomSheet>
It works fine
4 months without maintainer response. Abandoned? 🤔
4 months without maintainer response. Abandoned? 🤔
There have been releases since then, could you double check if the bug still exists in the latest version? An up-to-date minimal reproduction would be very useful
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
The issue is still persist