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
相关产品推荐
相关产品推荐

