React Native使用AsyncStorage实现登录记忆时的路由跳转异常问题
问题分析与解决
核心问题
- 异步函数返回Promise而非布尔值:
ch()是异步函数,执行后返回的是Promise对象,而非你期望的布尔值。JavaScript中Promise属于"真值",所以check ? AppNavigator2 : AppNavigator永远会选中AppNavigator2,导致无论登录状态如何都跳转到这个导航。 - 同步创建导航容器无法等待异步操作:
createAppContainer是同步执行的,此时AsyncStorage的读取操作还未完成,初始判断根本拿不到真实的登录状态。 - 冗余的导航器定义:两个导航器内容完全一致,只是初始页面不同,没必要重复定义。
修复后的代码
import { createAppContainer } from 'react-navigation'; import { createStackNavigator } from 'react-navigation-stack'; import Login from './components/login' import Signup from './components/signup' import Home from './components/home' import Profile from './components/profile'; import AsyncStorage from '@react-native-async-storage/async-storage'; import React, { useState, useEffect } from 'react'; import { ActivityIndicator, View } from 'react-native'; // 只定义一个导航器,通过initialRouteName控制初始页面 const AppNavigator = createStackNavigator({ Login: { screen: Login }, Signup: { screen: Signup }, Home: { screen: Home }, Profile: { screen: Profile }, }); const AppContainer = createAppContainer(AppNavigator); const App = () => { // isLoggedIn初始为null,表示正在加载登录状态 const [isLoggedIn, setIsLoggedIn] = useState(null); useEffect(() => { const checkLoginStatus = async () => { try { const value = await AsyncStorage.getItem('@userauthkey'); // 根据是否获取到值设置登录状态 setIsLoggedIn(value !== null); } catch (e) { console.error('读取登录状态失败:', e); // 出错时默认设为未登录 setIsLoggedIn(false); } }; checkLoginStatus(); }, []); // 加载状态时显示加载指示器 if (isLoggedIn === null) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <ActivityIndicator size="large" /> </View> ); } // 根据登录状态设置导航器的初始页面 return <AppContainer screenProps={{ initialRouteName: isLoggedIn ? 'Home' : 'Login' }} />; }; export default App;
关键修改说明
- 用React状态管理登录状态:通过
useState存储登录状态,初始值null表示正在加载,避免同步判断的问题。 - 在useEffect中异步读取存储:组件挂载后执行异步操作,获取到登录状态后更新状态,触发组件重新渲染。
- 合并导航器:只定义一个导航器,通过
screenProps传递initialRouteName,动态设置初始页面,减少冗余代码。 - 添加加载状态提示:在读取存储的过程中显示加载指示器,提升用户体验。
内容的提问来源于stack exchange,提问作者Itay Lador
相关产品推荐
相关产品推荐

