You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native用户状态Provider导航栈切换异常:登出未跳转登录页

解决登出后无法自动跳转回登录页的问题

问题根源

  1. Router组件状态更新逻辑错误:使用useRef存储认证状态,且在useEffect的清理函数中更新——清理函数仅在组件卸载或依赖项变化前执行,无法实时响应me的变化;同时useRef的变更不会触发组件重渲染,导致导航栈不会切换。
  2. 登出操作未更新全局用户状态:Home页的closeSesion仅清除了AsyncStorage的数据,但未调用UserContext的setMe将用户状态置空,导致全局的me仍保持登录状态,Router无法感知登出。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 19:55:14