React Native/Expo应用登出后未自动跳转至认证页面问题
Expo Router 登出后无法自动跳转到认证页面的解决方案
你的核心问题是:RootLayout仅在初始加载时根据user状态渲染不同路由栈,但user状态变化(比如登出设为null)时,Expo Router的路由状态未同步更新,导致已加载的(tabs)页面仍可访问。
修复方案
1. 修改RootLayout,监听user状态自动跳转路由
更新Root.tsx,添加对user状态的监听,通过router.replace强制切换路由栈,实现统一的认证跳转逻辑:
import { router, Stack } from 'expo-router'; import { StatusBar } from 'expo-status-bar'; import React, { useContext, useEffect, useState } from 'react'; import 'react-native-reanimated'; import "./global.css"; import { View, Text } from 'react-native'; import { AuthContext } from '@/context/AuthProvider' export default function RootLayout() { const [isLoading, setisLoading] = useState(true) const { user } = useContext(AuthContext) useEffect(() => { setTimeout(() => { setisLoading(false) }, 2000) }, []) // 监听user状态变化,自动切换路由 useEffect(() => { if (!isLoading) { user ? router.replace('/(tabs)') : router.replace('/(auth)') } }, [user, isLoading]) if(isLoading) { return ( <View> <Text>Loading...</Text> </View> ) } // 统一渲染所有路由配置,跳转逻辑由useEffect处理 return ( <View className="h-full"> <Stack screenOptions={{ headerShown: false }}> <Stack.Screen name="(tabs)" /> <Stack.Screen name="(auth)" /> <Stack.Screen name="+not-found" /> </Stack> <StatusBar style="auto" /> </View> ); }
2. 优化AuthProvider的状态更新(可选)
你当前login/logout中的console.log(user)会打印旧值,因为setUser是异步操作,若需要在状态更新后执行逻辑,可改用回调形式:
import React, { createContext, useState } from "react"; export const AuthContext = createContext(); export const AuthProvider = ({children}) => { const [user, setUser] = useState(null) return ( <AuthContext.Provider value = {{ user, setUser, login: (email, password) => { console.log('login') setUser(() => { const newUser = 'Thomas'; console.log(newUser); return newUser; }) }, logout: () => { console.log('logout') setUser(null) } }} > {children} </AuthContext.Provider> ) }
原理说明
Expo Router的Stack组件仅用于定义路由规则,而非触发跳转。初始加载时的条件渲染只是加载了对应路由配置,但不会重置已激活的路由栈。通过监听user状态并调用router.replace,可以强制替换当前路由栈,实现登录/登出时的自动跳转,无需在logout函数中手动处理跳转逻辑。
内容的提问来源于stack exchange,提问作者Mosh
相关产品推荐
相关产品推荐

