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

React页面刷新后保持登录状态的实现及报错解决

问题解决:修复onLogin报错+实现刷新保持登录

一、先解决「onLogin is not a function」报错

你的核心问题是AuthContext没有向子组件暴露onLogin方法,反而把底层的loginRequest放进了上下文,同时组件挂载时还无参数调用了onLogin(),直接导致报错。按以下步骤修改authcontext.js:

import { loginRequest } from "./authentication.service";
import React, { createContext, useEffect, useState } from "react";

// 必须显式创建Context,原代码漏了这一步
export const AuthContext = createContext();

export const AuthContextProvider = ({ children }) => {
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState(null);
    const [user, setUser] = useState(null);

    // 把onLogin定义为组件顶层函数,而非useEffect内部
    const onLogin = async (email, password) => {
        setIsLoading(true);
        setError(null);
        try {
            const success = await loginRequest(email, password);
            if (success) {
                // 可根据需求调用Django用户详情接口,设置实际用户对象
                setUser(true); 
            }
        } catch (e) {
            setError(e.toString());
        } finally {
            setIsLoading(false);
        }
    };

    return (
        <AuthContext.Provider
            value={{
                isAuthenticated: !!user,
                isLoading,
                error,
                user,
                onLogin // 向子组件暴露onLogin方法
            }}>
            {children}
        </AuthContext.Provider>
    );
};

二、实现页面刷新后保持登录状态

要实现刷新后自动恢复登录,需要在组件挂载时读取AsyncStorage里的token,验证其有效性后恢复用户状态:

1. 在authservice添加token验证方法

export const validateToken = async () => {
    try {
        const token = await AsyncStorage.getItem("Token");
        if (!token) return false;
        
        // 调用Django后端的token验证接口(需自行实现)
        const response = await fetch(`${API_URL}/api/user/validate-token/`, {
            method: "GET",
            headers: {
                "Authorization": `Token ${token}`,
                "Content-Type": "application/json",
            },
        });
        
        return response.ok;
    } catch (error) {
        console.error("Token验证失败:", error);
        return false;
    }
};

注:Django后端需实现/api/user/validate-token/接口,或直接调用用户详情接口,返回200则代表token有效。

2. 在authcontext添加初始化登录状态逻辑

修改authcontext的useEffect:

import { loginRequest, validateToken } from "./authentication.service";
// ...其他代码

export const AuthContextProvider = ({ children }) => {
    // ...状态定义

    // 组件挂载时初始化登录状态
    useEffect(() => {
        const initAuth = async () => {
            setIsLoading(true);
            const isTokenValid = await validateToken();
            if (isTokenValid) {
                setUser(true); // 或设置实际用户信息
            } else {
                await AsyncStorage.removeItem("Token"); // 清除无效token
                setUser(null);
            }
            setIsLoading(false);
        };
        initAuth();
    }, []);

    // ...onLogin函数和其他代码
};

3. 完善loginRequest的错误处理

原代码catch块未抛出错误,导致Promise不会reject,修改后让错误能被上下文捕获:

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 true;
        } else {
            throw new Error(data.detail || "邮箱或密码错误");
        }
    } catch (error) {
        console.error(error);
        throw new Error(error.message || "登录失败,请重试");
    }
};

三、额外优化点

  • LoginScreen的ActivityIndicator需设置animating={isLoading},原代码写死false会导致加载时不转动:
<ActivityIndicator animating={isLoading} />
  • 新增登出功能(可选):在authcontext里添加onLogout方法并暴露给子组件:
const onLogout = async () => {
    await AsyncStorage.removeItem("Token");
    setUser(null);
};
// 在Provider的value里添加onLogout

内容的提问来源于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.02 07:20:17