React Native/Expo如何修复代码使模态框仅从结束页回首页时弹出一次
问题原因分析
异常1:模态框偶发不弹出
useFocusEffect包裹的useCallback依赖数组为空,无法响应route.params的更新,部分场景下路由参数更新后不会触发模态框判断逻辑- 原代码在
useFocusEffect的清理函数中直接强制关闭模态框,页面失焦时会抵消弹出逻辑,导致偶发失效
异常2:从Profile页返回首页模态框意外弹出
React Navigation的路由参数为持久化存储,从FinishingScreen跳转时带入的didComeFromFinishingScreen: true参数会一直保留在HomeScreen的路由参数中,后续每次回到首页触发useFocusEffect都会读到真值,导致重复弹出。
修复方案
仅需要修改HomeScreen中的useFocusEffect逻辑即可,核心修改点:
- 将
route、navigation加入useCallback依赖数组,确保路由参数更新时能触发判断逻辑 - 模态框触发后立刻重置路由参数,清空
didComeFromFinishingScreen标识,避免后续重复触发 - 清理函数仅处理未完成的异步请求,不要强制关闭模态框,模态框关闭逻辑交给用户交互触发
修改后的代码如下:
// 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
相关产品推荐
相关产品推荐

