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

React Native Web登录后页面刷新时如何持久化Token?

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

你的代码存在几个关键问题,导致登录后刷新页面会回到登录界面,以下是针对性的修复方案:

1. 修正Token的初始化与挂载读取逻辑

  • 不能直接在useState中使用AsyncStorageLib.getItem("Token"),这是异步操作,初始值会是Promise而非实际的Token字符串。
  • 需要在组件挂载时通过useEffect读取本地保存的Token,并更新到状态中,同时处理加载状态。

2. 修复登录逻辑的状态更新

  • 你的loginRequest返回的是true,但onLogin中试图读取u.token,这会导致token被设为undefined,需要修正登录成功后的状态更新逻辑。

3. 完善认证状态判断逻辑

  • 原代码中isAuthenticated依赖user状态,但刷新后user为null,应该结合token来判断用户是否已登录,或者通过Token重新获取用户信息。

修改后的AuthContext代码

import { createContext, useState, useEffect } from "react";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { loginRequest } from "./path-to-your-login-service"; // 替换为实际文件路径
import { useToast } from "react-native-toast-notifications";

export const AuthContext = createContext();

export const AuthContextProvider = ({ children }) => {
    const [isLoading, setIsLoading] = useState(true); // 初始设为true,等待Token读取完成
    const [error, setError] = useState(null);
    const [token, setToken] = useState(null);
    const [user, setUser] = useState(null);
    const toast = useToast();

    // 组件挂载时读取本地Token
    useEffect(() => {
        const loadSavedToken = async () => {
            try {
                const savedToken = await AsyncStorage.getItem("Token");
                if (savedToken) {
                    setToken(savedToken);
                    // 可选:调用API用Token获取用户信息,更新user状态
                    // const userInfo = await fetchUserProfile(savedToken);
                    // setUser(userInfo);
                }
            } catch (err) {
                console.error("读取Token失败:", err);
                setError(err.message);
            } finally {
                setIsLoading(false);
            }
        };

        loadSavedToken();
    }, []);

    const onLogin = (email, password) => {
        setIsLoading(true);
        loginRequest(email, password)
            .then(() => AsyncStorage.getItem("Token"))
            .then(fetchedToken => {
                setToken(fetchedToken);
                // 可选:同步获取用户信息
                // const userInfo = await fetchUserProfile(fetchedToken);
                // setUser(userInfo);
                setIsLoading(false);
            })
            .catch((e) => {
                setIsLoading(false);
                toast.show("Email of wachtwoord incorrect. Probeer het nog eens", { type: "warning" });
            });
    };

    // 可选:添加登出逻辑
    const onLogout = async () => {
        try {
            await AsyncStorage.removeItem("Token");
            setToken(null);
            setUser(null);
        } catch (err) {
            console.error("登出失败:", err);
        }
    };

    return (
        <AuthContext.Provider
            value={{
                isAuthenticated: !!token, // 用token判断登录状态
                isLoading,
                error,
                user,
                token,
                onLogin,
                onLogout
            }}>
            {!isLoading && children} {/* 加载完成后再渲染子组件,避免闪烁 */}
        </AuthContext.Provider>
    );
};

可选:调整loginRequest返回值

如果希望登录后直接拿到Token,可以修改loginRequest,让它返回token而非布尔值:

export const loginRequest = async (email, password) => {    
    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.token; // 返回token,简化登录后的状态更新
    } else {
        throw new Error(data.detail || "登录失败"); // 使用更准确的错误信息
    }
};

关键说明

  • 页面刷新时,useEffect会自动从AsyncStorage读取保存的Token并更新状态,isAuthenticated会正确识别用户已登录状态。
  • 初始加载状态设为true,避免刷新时短暂显示登录页再跳转的问题。
  • 认证状态依赖token而非user,因为刷新后user需要重新获取,而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.06.29 21:37:44