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

React Native/Expo如何修复代码使模态框仅从结束页回首页时弹出一次

问题原因分析

异常1:模态框偶发不弹出

  • useFocusEffect包裹的useCallback依赖数组为空,无法响应route.params的更新,部分场景下路由参数更新后不会触发模态框判断逻辑
  • 原代码在useFocusEffect的清理函数中直接强制关闭模态框,页面失焦时会抵消弹出逻辑,导致偶发失效

异常2:从Profile页返回首页模态框意外弹出

React Navigation的路由参数为持久化存储,从FinishingScreen跳转时带入的didComeFromFinishingScreen: true参数会一直保留在HomeScreen的路由参数中,后续每次回到首页触发useFocusEffect都会读到真值,导致重复弹出。


修复方案

仅需要修改HomeScreen中的useFocusEffect逻辑即可,核心修改点:

  1. 将route、navigation加入useCallback依赖数组,确保路由参数更新时能触发判断逻辑
  2. 模态框触发后立刻重置路由参数,清空didComeFromFinishingScreen标识,避免后续重复触发
  3. 清理函数仅处理未完成的异步请求,不要强制关闭模态框,模态框关闭逻辑交给用户交互触发

修改后的代码如下:

// HomeScreen 仅展示修改后的useFocusEffect部分,其余代码保持不变
useFocusEffect(
  React.useCallback(()=>{
    // 用于标记当前组件是否激活,避免异步请求完成后给卸载的组件赋值
    let isActive = true

    async function getLocationAsync(){
      let {status} = await Location.requestForegroundPermissionsAsync()
      if(status !== 'granted'){
        setErrorMsg('Permission to access location was denied')
        return
      }
      let location = await Location.getCurrentPositionAsync({})
      // 仅组件激活时更新状态
      if(isActive) setLocation(location)
    }

    if(route.params?.didComeFromFinishingScreen) {
      console.log('didComeFromFinishingScreen is attempting to open modal')
      setModalVisible(true)
      // 立刻重置路由参数,清除标识,避免后续重复触发
      navigation.setParams({ didComeFromFinishingScreen: false })
    }
    
    getLocationAsync()

    return()=>{
      console.log('cleanup function runs')
      // 标记组件失活,终止异步逻辑更新
      isActive = false
    }
  },
  // 加入依赖,确保路由参数变化时重新执行逻辑
  [route, navigation],
  )
)

效果验证
  • 从FinishingScreen跳转回HomeScreen时,路由参数携带真值,触发模态框弹出,随后参数立刻被重置为假
  • 后续从Profile等其他页面返回HomeScreen时,路由参数已经为假,不会触发模态框弹出
  • 依赖数组更新后,每次页面获得焦点都会读取最新的路由参数,不会出现偶发不触发的问题

内容的提问来源于stack exchange,提问作者shyguy189540

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 05:45:04