React Native中调用bottomSheetRef.close()后Bottom Sheet无法关闭
修复React Native中BottomSheet修改isLoading后无法关闭的问题
当前代码中,调用applyFilters()时,先设置isLoading=true再调用bottomSheetRef.current?.close(),BottomSheet无法正常关闭;但仅调用close()时可以正常关闭。
原因分析
- BottomSheet的index未受控:当前BottomSheet的
index属性硬编码为-1,未通过状态管理。当组件因isLoading变化重渲染时,BottomSheet会收到固定的index=-1props,与内部展开状态(index=0)产生冲突,干扰关闭逻辑。 - footerComponent频繁重创建:
filtersFooter函数在每次组件渲染时都会重新生成,作为footerComponent传给BottomSheet,导致BottomSheet内部频繁重渲染,打断关闭动画或状态更新。
修复方案
方案1:改用受控方式管理BottomSheet状态(推荐)
通过状态控制BottomSheet的展开/关闭,替代ref调用的方式,避免重渲染带来的冲突:
const ListingScreen = () => { // 新增状态管理BottomSheet的index const [bottomSheetIndex, setBottomSheetIndex] = useState<number>(-1); // ...其他原有状态 function showFilters() { setBottomSheetIndex(0); // 展开BottomSheet } async function applyFilters() { setIsLoading(true); setBottomSheetIndex(-1); // 关闭BottomSheet,受控方式更可靠 setTimeout(() => { setIsLoading(false); }, 500); } // ...其他原有代码 return ( // ...其他原有组件 <BottomSheet ref={bottomSheetRef} index={bottomSheetIndex} // 使用受控状态 snapPoints={snapPoints} enablePanDownToClose={true} footerComponent={filtersFooter} onIndexChange={setBottomSheetIndex} // 同步用户手动关闭的状态 > {/* ...BottomSheet原有内容 */} </BottomSheet> ); };
方案2:缓存footerComponent避免频繁重渲染
使用useCallback包裹filtersFooter和applyFilters函数,确保每次渲染时引用不变,防止BottomSheet不必要的重渲染:
// 用useCallback包裹applyFilters const applyFilters = useCallback(async () => { setIsLoading(true); bottomSheetRef.current?.close(); setTimeout(() => { setIsLoading(false); }, 500); }, []); // 用useCallback包裹filtersFooter const filtersFooter = useCallback(() => { return ( <View className="items-center bg-red-transparent"> <Pressable className="w-auto h-auto mb-6 bg-cyan-500 rounded-lg py-3 px-6 flex items-center" onPress={applyFilters} > <Text className="text-white font-semibold ">Apply filters</Text> </Pressable> </View> ); }, [applyFilters]);
额外优化点
原useEffect未设置依赖项,会导致组件每次渲染都重复执行,应添加空依赖数组确保仅在组件挂载时执行一次:
useEffect(() => { setTimeout(() => { getListings() .then((listingsData) => setListings(listingsData)) .catch((err) => Alert.alert("server error")) .finally(() => setIsLoading(false)); }, 500); }, []); // 添加空依赖数组
内容的提问来源于stack exchange,提问作者Alexxosipov
相关产品推荐
相关产品推荐

