React中如何在组件渲染前调用异步函数?(私有路由鉴权场景)
解决React私有路由异步登录校验问题
第一步:修正AuthService的isLoggedIn函数
你的isLoggedIn函数存在两个问题:一是没有返回axios请求的Promise,二是未处理请求失败的情况。修改后确保它能正确返回布尔值的Promise:
import axios from 'axios'; class AuthService { api_domain = "http://localhost:5000"; async isLoggedIn() { const token = this.getToken(); // 先检查本地是否存在有效Token if (!token || typeof token !== 'string') { return false; } try { // 用await简化异步逻辑,同时捕获请求失败的情况 const res = await axios.get(`${this.api_domain}/`, { headers: { Authorization: token } }); return res.data.status === 'ok'; } catch (error) { // 请求失败(Token过期、网络错误等)一律判定为未登录 return false; } } // 补充getToken实现(假设从localStorage读取) getToken() { return localStorage.getItem('token'); } } export const authService = new AuthService();
第二步:改造PrivateRoute组件处理异步校验
React组件渲染是同步的,不能直接在渲染阶段调用异步函数,需要用状态管理校验过程和结果:
import { useState, useEffect } from 'react'; import { useLocation, Navigate } from 'react-router-dom'; import { authService } from '../authservice/AuthService'; export default function PrivateRoute({ children }: { children: JSX.Element }) { // null表示校验未完成,true/false表示校验结果 const [isLoggedIn, setIsLoggedIn] = useState<boolean | null>(null); const location = useLocation(); useEffect(() => { // 在组件挂载时执行异步校验 const checkAuthentication = async () => { const result = await authService.isLoggedIn(); setIsLoggedIn(result); }; checkAuthentication(); }, []); // 校验过程中显示加载状态(避免页面闪烁) if (isLoggedIn === null) { return <div>校验中...</div>; // 可替换为自定义加载组件 } // 校验未通过则跳转到登录页,记录当前位置以便登录后跳转回来 if (!isLoggedIn) { return <Navigate to="/login" state={{ from: location }} replace />; } // 校验通过则渲染受保护的子组件 return children; }
核心逻辑说明
- 用
useState维护校验状态:isLoggedIn初始为null,表示正在校验;校验完成后更新为true或false - 用
useEffect在组件挂载时触发异步校验,确保只执行一次 - 校验过程中显示加载UI,避免用户看到未授权内容或突然跳转
- 捕获请求失败的情况,统一判定为未登录,覆盖Token过期、网络异常等场景
内容的提问来源于stack exchange,提问作者Petar18
相关产品推荐
相关产品推荐

