React Navigation 6.x:能否为Stack.Screen添加onFocus函数存储当前屏幕?
方案1:全局监听导航状态变化(推荐)
无需逐个修改屏幕,直接在导航容器上监听状态变更,路由切换时自动将当前屏幕名称存入AsyncStorage,是最简洁的实现方式。
import { NavigationContainer } from '@react-navigation/native'; import AsyncStorage from '@react-native-async-storage/async-storage'; function App() { return ( <NavigationContainer onStateChange={(state) => { // 获取当前活跃路由的名称 const currentScreen = state.routes[state.index].name; // 存入AsyncStorage AsyncStorage.setItem('currentScreen', currentScreen); }} > <Stack.Navigator> <Stack.Screen name="ResolveAuth" component={ResolveAuthScreen} options={{ headerShown: false }} /> <Stack.Screen name="Home" component={HomeScreen} /> {/* 其他屏幕组件 */} </Stack.Navigator> </NavigationContainer> ); }
如果不想保存ResolveAuth这类过渡屏幕,可以在监听逻辑里过滤:
onStateChange={(state) => { const currentScreen = state.routes[state.index].name; if (currentScreen !== 'ResolveAuth') { AsyncStorage.setItem('currentScreen', currentScreen); } }}
方案2:用高阶组件(HOC)封装屏幕追踪逻辑
如果需要按需给屏幕添加追踪(部分屏幕不需要保存),可以封装一个高阶组件,复用监听逻辑,保持原组件干净。
import { useFocusEffect } from '@react-navigation/native'; import AsyncStorage from '@react-native-async-storage/async-storage'; import React from 'react'; // 定义高阶组件 const withScreenTracker = (WrappedComponent, screenName) => { return (props) => { useFocusEffect( React.useCallback(() => { // 屏幕获取焦点时保存名称 AsyncStorage.setItem('currentScreen', screenName); // 可选:屏幕失焦时的清理操作 return () => {}; }, [screenName]) ); return <WrappedComponent {...props} />; }; }; // 给需要追踪的屏幕组件套上HOC const TrackedHomeScreen = withScreenTracker(HomeScreen, 'Home'); const TrackedResolveAuthScreen = withScreenTracker(ResolveAuthScreen, 'ResolveAuth'); // 在Stack.Screen中使用封装后的组件 <Stack.Screen name="ResolveAuth" component={TrackedResolveAuthScreen} options={{ headerShown: false }} /> <Stack.Screen name="Home" component={TrackedHomeScreen} />
方案3:直接在Stack.Screen的options中配置listener
如果你希望直接在<Stack.Screen>上完成配置,可以利用React Navigation 6.x提供的options.listener属性,监听屏幕的focus事件:
import AsyncStorage from '@react-native-async-storage/async-storage'; <Stack.Screen name="Home" component={HomeScreen} options={{ listener: ({ navigation }) => { // 订阅focus事件 const unsubscribe = navigation.addListener('focus', () => { AsyncStorage.setItem('currentScreen', 'Home'); }); // 组件卸载时取消订阅 return unsubscribe; }, }} /> // ResolveAuth屏幕同理 <Stack.Screen name="ResolveAuth" component={ResolveAuthScreen} options={{ headerShown: false, listener: ({ navigation }) => { const unsubscribe = navigation.addListener('focus', () => { AsyncStorage.setItem('currentScreen', 'ResolveAuth'); }); return unsubscribe; }, }} />
注意事项
- AsyncStorage是异步操作,若需确保保存完成后执行后续逻辑,可在回调中使用
async/await:navigation.addListener('focus', async () => { await AsyncStorage.setItem('currentScreen', 'Home'); // 后续逻辑 });
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

