如何让React Navigation的focusHandler仅响应抽屉导航切换?
解决方案
要实现仅在抽屉导航切换时触发firstFunc,而栈内跳转返回不触发,核心是区分焦点来源是抽屉切换还是栈内导航——前者会改变抽屉导航的活跃路由,后者只会改变嵌套栈的状态。
具体实现步骤
- 获取抽屉导航实例:由于
FirstScreen嵌套在Stack导航中,而Stack又是抽屉的子页面,需要通过两次dangerouslyGetParent()拿到抽屉导航的引用。 - 监听抽屉导航的状态变化:当抽屉的活跃路由切换到
First且之前不是First时,执行目标函数。
import { useNavigation, useState, useEffect } from '@react-navigation/native'; // 从FirstContext中获取firstFunc import { useFirstContext } from '../path/to/FirstContext'; function FirstScreen({ navigation }) { const { firstFunc } = useFirstContext(); // 获取当前页面的父级Stack导航 const stackNav = navigation.dangerouslyGetParent(); // 获取Stack导航的父级抽屉导航 const drawerNav = stackNav?.dangerouslyGetParent(); // 记录上一次抽屉的活跃路由 const [prevDrawerActiveRoute, setPrevDrawerActiveRoute] = useState(null); useEffect(() => { if (!drawerNav) return; // 初始化时记录当前抽屉的活跃路由 const initialRoute = drawerNav.getCurrentRoute()?.name; setPrevDrawerActiveRoute(initialRoute); // 监听抽屉导航的状态变化 const handleDrawerStateChange = () => { const currentActiveRoute = drawerNav.getCurrentRoute()?.name; // 仅当抽屉从其他页面切换到First时触发函数 if (currentActiveRoute === 'First' && prevDrawerActiveRoute !== 'First') { firstFunc(); } // 更新上一次的活跃路由记录 setPrevDrawerActiveRoute(currentActiveRoute); }; const unsubscribe = drawerNav.addListener('state', handleDrawerStateChange); // 组件卸载时取消监听 return unsubscribe; }, [drawerNav, firstFunc]); // ... 组件其他逻辑 }
关键说明
- 为什么不用原有的
focus监听?因为focus事件会在任何场景下屏幕获得焦点时触发,包括栈内从FirstDetail返回FirstScreen的情况,无法区分来源。 - 如果需要首次进入
First页面时也触发firstFunc,可以调整判断条件为:if (currentActiveRoute === 'First' && (prevDrawerActiveRoute !== 'First' || prevDrawerActiveRoute === null)) { firstFunc(); }
内容的提问来源于stack exchange,提问作者extradeck
相关产品推荐
相关产品推荐

