React Native用户状态Provider导航栈切换异常:登出未跳转登录页
解决登出后无法自动跳转回登录页的问题
问题根源
- Router组件状态更新逻辑错误:使用
useRef存储认证状态,且在useEffect的清理函数中更新——清理函数仅在组件卸载或依赖项变化前执行,无法实时响应me的变化;同时useRef的变更不会触发组件重渲染,导致导航栈不会切换。 - 登出操作未更新全局用户状态:Home页的
closeSesion仅清除了AsyncStorage的数据,但未调用UserContext的setMe将用户状态置空,导致全局的me仍保持登录状态,Router无法感知登出。 - UserProvider初始状态不明确:
me初始值为undefined,判断me !== null会出现逻辑模糊的情况。
修复步骤
1. 修正Router组件的状态判断逻辑
去掉useRef,直接根据me的值判断渲染导航栈,同时处理初始加载的过渡状态:
import { NavigationContainer } from "@react-navigation/native" import React, { useContext } from "react" import { UserContext } from "./context/Usuario" import AuthStack from "./routes/AuthStack" import GeneralStack from "./routes/GeneralStack" import SplashScreen from "./SplashScreen" const Router = () => { const { me } = useContext(UserContext) // 初始加载时显示启动页 if (me === undefined) { return <SplashScreen /> } return ( <NavigationContainer> {me !== null ? <GeneralStack /> : <AuthStack />} </NavigationContainer> ) } export default Router
2. 修正UserProvider的初始状态
将me的初始值设为null,明确未认证状态:
import React, { useEffect, createContext, useState } from "react" import AsyncStorage from "@react-native-async-storage/async-storage" export const UserContext = createContext() const UserProvider = ({ children }) => { // 初始状态设为null,明确未认证状态 const [me, setMe] = useState(null) const validStorage = async () => { try { const miSesion = await AsyncStorage.getItem("sesion") console.log(miSesion) // 有数据则解析,否则保持null setMe(miSesion ? JSON.parse(miSesion) : null) } catch (error) { console.log(`ERROR: ${error.message}`) setMe(null) } } useEffect(() => { validStorage() }, []) return ( <UserContext.Provider value={{ me, setMe }}> {children} </UserContext.Provider> ) } export default UserProvider
3. 修复Home页的登出逻辑
登出时同时清除AsyncStorage并更新全局用户状态:
import AsyncStorage from "@react-native-async-storage/async-storage" import React, { useState, useContext } from "react" import { Image, ScrollView, TouchableOpacity } from "react-native" import { Calendar } from "react-native-calendars" import { Text } from "react-native-elements" import { useNavigate } from "../../Hooks/useNavigate" import colors from "../../styles/colors" import { UserContext } from "../../context/Usuario" const Home = () => { const [showModal, setShowModal] = useState(false) const [date, setDate] = useState<string>() const navigate = useNavigate() const { setMe } = useContext(UserContext) const closeSesion = async () => { await AsyncStorage.removeItem("sesion") // 更新全局用户状态为null,触发Router切换导航栈 setMe(null) } return ( <ScrollView> <TouchableOpacity onPress={() => closeSesion()}> <Text>Hola porque soy bien molon</Text> </TouchableOpacity> <Image source={require("../../recursos/images/coralio_logo.png")} style={{ marginTop: 40, height: 110, width: "80%", justifyContent: "center", alignSelf: "center", }} /> <Calendar theme={{ selectedDayBackgroundColor: colors.BLACK, arrowColor: colors.WHITE, monthTextColor: colors.WHITE, }} style={{ backgroundColor: colors.PURPLE, borderRadius: 10, elevation: 4, marginTop: 60, margin: 10, height: 400, }} onDayPress={day => { console.log(day.dateString) setDate(day.dateString) setShowModal(false) }} onMonthChange={() => {}} initialDate="2023-01-16" minDate={new Date() .toLocaleDateString("es-US", { year: "numeric", month: "2-digit", day: "numeric", formatMatcher: "basic", }) .split("/") .reverse() .join("-")} markedDates={{ day: { marked: true, dotColor: colors.WHITE, selected: true, selectedColor: colors.PURPLE, }, }} /> </ScrollView> ) } export default Home
4. 优化Login页的冗余代码
移除Login页中冗余的本地状态,依赖全局UserContext管理登录状态:
// 移除以下冗余代码 // const [, setIsSession] = useState(false) // const getStorage = async () => { ... } const signIn = async () => { try { console.log(user) if (form.user === user.user && form.password === user.password) { await AsyncStorage.setItem("sesion", JSON.stringify(form)) setMe(form) // 移除setIsSession(true),全局状态更新后Router会自动切换导航栈 } } catch (error) { console.error(error) } }
验证逻辑
- 登录:调用
setMe(form)后,me变为非null,Router自动渲染GeneralStack,切换到已认证导航。 - 登出:调用
setMe(null)后,me变为null,Router感知状态变化,自动切换到AuthStack,回到登录页。
内容的提问来源于stack exchange,提问作者Sebastian Casadiego
相关产品推荐
相关产品推荐

