React Native点击登录按钮出现NAVIGATE未被导航器处理错误
问题描述
在React Native应用中实现AWS自定义UI认证与React Navigation页面导航,设置了已登录用户跳转至Home页面、未登录用户跳转至Login页面的逻辑,基础导航功能正常,但点击登录按钮时控制台报错:
ERROR The action 'NAVIGATE' with payload {"name":"Home"} was not handled by any navigator
问题根源
当前导航组件的逻辑是根据user状态条件渲染不同的栈屏幕:
- 未登录时,导航栈仅包含Login、Register等未授权页面
- 登录成功后调用
navigation.navigate('Home')时,user状态尚未更新,Home屏幕还未被添加到当前导航栈中,导致导航器找不到对应路由,抛出错误。
虽然Hub会监听auth的signIn事件并触发checkUser()更新user状态,最终会切换到Home页面,但手动导航的时机早于状态更新,因此报错。
解决方案
方案1:移除手动导航,依赖状态更新自动切换(推荐)
既然已经通过user状态控制导航栈渲染,登录成功后无需手动调用导航,等待Hub触发状态更新即可自动切换页面。
修改LoginScreen中的onLoginPressed函数:
const onLoginPressed = async (data) => { if(loading) { return; } setLoading(true); try { // 仅执行登录操作,移除手动导航逻辑 await Auth.signIn(data.username, data.password); // 登录成功后,Hub会监听signIn事件并更新user状态,导航组件自动切换到Home页面 } catch(e) { Alert.alert('Opps', e.message) } setLoading(false); };
方案2:始终加载所有屏幕,通过初始路由控制显示
如果希望保留手动导航逻辑,可修改导航组件,将所有屏幕加入栈中,通过initialRouteName根据用户状态控制初始显示页面:
修改Navigation组件:
const Navigation = () => { const [user, setUser] = useState(undefined); const checkUser = async () => { try { const authUser = await Auth.currentAuthenticatedUser({bypassCache: true}); setUser(authUser); } catch(e) { setUser(null); } }; useEffect(() => { checkUser(); }, []); useEffect(() => { const listener = data => { if (data.payload.event === 'signIn' || data.payload.event === 'signOut') { checkUser(); } } Hub.listen('auth', listener); return () => Hub.remove('auth', listener); }, []); if (user === undefined) { return ( <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}> <ActivityIndicator/> </View> ); } return ( <NavigationContainer> <Stack.Navigator // 根据用户状态设置初始路由 initialRouteName={user ? 'Home' : 'Login'} screenOptions={{headerShown: false}} > // 始终添加所有页面到导航栈 <Stack.Screen name='Home' component={HomeScreen}/> <Stack.Screen name='Login' component={LoginScreen}/> <Stack.Screen name='Register' component={RegisterScreen}/> <Stack.Screen name='ConfirmEmail' component={ConfirmEmailScreen}/> <Stack.Screen name='ForgotPassword' component={ForgotPassword}/> <Stack.Screen name='NewPassword' component={NewPasswordScreen}/> </Stack.Navigator> </NavigationContainer> ); };
此方案下,Home屏幕始终存在于导航栈中,登录后调用navigation.navigate('Home')可正常生效。
内容的提问来源于stack exchange,提问作者Imran Irshad
相关产品推荐
相关产品推荐

