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

React Native Web页面刷新后保持登录状态的实现方法

解决Expo React Native Web页面刷新后Token丢失的问题

问题根源很明确:页面刷新后React组件重新初始化,你的AuthContext里的user状态被重置为null,且未在组件挂载时从AsyncStorage读取之前保存的Token、恢复登录状态。

修复步骤:

1. 在认证上下文初始化时读取并恢复登录状态

修改AuthContextProvider,添加组件挂载逻辑,从AsyncStorage读取Token并验证有效性(可选但推荐),同步更新用户状态:

import {
    AccountRequest,
    AccountUpdateRequest,
    loginRequest,
    logoutRequest,
    registerRequest,
} from "./authentication.service";
import React, { createContext, useState, useEffect } from "react";
import AsyncStorage from '@react-native-async-storage/async-storage';

export const AuthContext = createContext();

export const AuthContextProvider = ({ children }) => {
    const [isLoading, setIsLoading] = useState(true); // 初始为true,处理初始化加载
    const [error, setError] = useState(null);
    const [user, setUser] = useState(null);

    // 组件挂载时检查登录状态
    useEffect(() => {
        const checkAuthStatus = async () => {
            try {
                const savedToken = await AsyncStorage.getItem("Token");
                if (savedToken) {
                    // 可选:调用后端接口验证Token有效性(比如获取用户信息)
                    // const response = await fetch(`${API_URL}/api/user/profile/`, {
                    //     headers: { "Authorization": `Bearer ${savedToken}` }
                    // });
                    // if (response.ok) {
                    //     const userData = await response.json();
                    //     setUser(userData); // 用真实用户信息更新状态
                    // } else {
                    //     await AsyncStorage.removeItem("Token"); // Token无效则清除
                    // }
                    
                    // 若暂时无验证接口,先将user设为true(匹配当前loginRequest返回值)
                    setUser(true);
                }
            } catch (err) {
                console.error("读取登录状态失败:", err);
                await AsyncStorage.removeItem("Token"); // 读取失败时清除无效Token
            } finally {
                setIsLoading(false); // 初始化完成
            }
        };

        checkAuthStatus();
    }, []);

    const onLogin = (email, password) => {
        setIsLoading(true);
        loginRequest(email, password)
            .then((u) => {
                setUser(u);
                setIsLoading(false);
            })
            .catch((e) => {
                setIsLoading(false);
                setError(e.toString());
            });
    };

    // 补充登出逻辑,确保清除Token
    const onLogout = async () => {
        try {
            await logoutRequest();
            await AsyncStorage.removeItem("Token");
            setUser(null);
        } catch (err) {
            console.error("登出失败:", err);
            setError(err.toString());
        }
    };

    return (
        <AuthContext.Provider
            value={{
                isAuthenticated: !!user,
                isLoading,
                error,
                user,
                onLogin,
                onRegister,
                onLogout,
                handleValidEmail,
                handleValidPassword,
                UserProfileRequest,
                UpdateUserProfileRequest,
            }}>
            {!isLoading && children} {/* 初始化完成后再渲染子组件,避免页面闪烁 */}
        </AuthContext.Provider>
    );
};

2. 优化登录请求返回值(可选)

当前loginRequest返回true,建议改为返回用户信息(若后端接口提供),让user状态存储真实用户数据:

export const loginRequest = async (email, password) => {
    try {
        const response = await fetch(`${API_URL}/api/user/token/`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({ email, password }),
        });

        const data = await response.json();

        if (response.ok) {
            await AsyncStorage.setItem("Token", data.token);
            // 若后端返回用户信息,直接返回
            // return data.user;
            // 否则返回含token的对象,方便后续使用
            return { token: data.token };
        } else {
            throw new Error(data.detail || "邮箱或密码错误");
        }
    } catch (error) {
        console.error("登录失败:", error);
        throw new Error("邮箱或密码输入错误");
    }
};

关键说明:

  • 组件挂载时通过useEffect读取AsyncStorage中的Token,是刷新页面后恢复登录状态的核心。
  • 验证Token有效性的步骤能避免使用过期/无效Token访问接口,提升安全性。
  • 登出时必须清除AsyncStorage中的Token,确保状态同步。

内容的提问来源于stack exchange,提问作者mightycode Newton

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 10:57:49