You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中调用bottomSheetRef.close()后Bottom Sheet无法关闭

修复React Native中BottomSheet修改isLoading后无法关闭的问题

当前代码中,调用applyFilters()时,先设置isLoading=true再调用bottomSheetRef.current?.close(),BottomSheet无法正常关闭;但仅调用close()时可以正常关闭。

原因分析

  1. BottomSheet的index未受控:当前BottomSheet的index属性硬编码为-1,未通过状态管理。当组件因isLoading变化重渲染时,BottomSheet会收到固定的index=-1 props,与内部展开状态(index=0)产生冲突,干扰关闭逻辑。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 17:37:49