React Navigation 6.x:如何全局监听所有导航器的屏幕事件?
可以实现仅通过一次监听调用,在屏幕组件外部全局监听所有屏幕的导航事件(如聚焦、失焦),以下是两种可行方案:
方案一:利用NavigationContainer的onStateChange回调
onStateChange会在导航状态发生任何变化时触发,通过对比前后状态的路由信息,就能追踪屏幕的聚焦/失焦状态。
import { NavigationContainer } from '@react-navigation/native'; import { useEffect, useRef } from 'react'; function App() { // 保存上一次的导航状态 const previousStateRef = useRef(null); const handleStateChange = (currentState) => { const previousState = previousStateRef.current; if (previousState) { const previousRoute = previousState.routes[previousState.index]; const currentRoute = currentState.routes[currentState.index]; // 检测屏幕切换,触发失焦/聚焦逻辑 if (previousRoute.name !== currentRoute.name) { console.log(`屏幕 ${previousRoute.name} 已失焦`); console.log(`屏幕 ${currentRoute.name} 已聚焦`); } } previousStateRef.current = currentState; }; return ( <NavigationContainer onStateChange={handleStateChange}> {/* 你的导航结构(Stack/Tabs/Drawer) */} </NavigationContainer> ); }
方案二:通过导航容器Ref订阅state事件
使用useNavigationContainerRef获取导航容器的引用,然后订阅全局的state事件,同样通过状态对比来监听屏幕切换:
import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native'; import { useEffect } from 'react'; function App() { const navigationRef = useNavigationContainerRef(); useEffect(() => { const unsubscribe = navigationRef.addListener('state', (event) => { const { previousState, state } = event.data; if (previousState) { const previousRoute = previousState.routes[previousState.index]; const currentRoute = state.routes[state.index]; if (previousRoute.name !== currentRoute.name) { console.log(`屏幕 ${previousRoute.name} 失焦`); console.log(`屏幕 ${currentRoute.name} 聚焦`); } } }); // 组件卸载时取消订阅 return unsubscribe; }, [navigationRef]); return ( <NavigationContainer ref={navigationRef}> {/* 你的导航结构 */} </NavigationContainer> ); }
注意事项
- 这两种方案主要针对屏幕聚焦/失焦这类由路由切换触发的事件;如果需要监听
beforeRemove这类屏幕级别的生命周期事件,全局监听无法直接覆盖,仍需在对应屏幕组件内单独处理。 - 你的
@react-navigation/native6.0.10版本完全支持上述API,无需担心兼容性问题。
内容的提问来源于stack exchange,提问作者Żabojad
相关产品推荐
相关产品推荐

