React路由守卫ProtectedRoute的return变量无法获取API调用返回正确值
问题根源
useRef变更不会触发组件重渲染:你修改isAuthenticated.current后,组件不会重新执行渲染逻辑,路由判断始终使用初始化的false值,因此一直重定向到登录页。- 异步请求时序问题:axios 登录校验是异步操作,组件首次渲染时请求还未返回结果,无论用
useRef还是useState,初始值都是false,首次渲染就会直接触发重定向,后续状态更新时组件已经被卸载,无法生效。 - 之前使用
useState未生效的核心原因是没有添加加载状态,请求未完成时就直接执行了路由判断逻辑。
解决方案
调整 ProtectedRoute 逻辑,添加加载状态,请求未返回前不做路由跳转判断,使用 useState 存储登录状态触发重渲染,修改后代码如下:
import React, { useEffect, useState } from "react"; import { Redirect, Route } from "react-router-dom"; import axios from 'axios' function ProtectedRoute({ component: Component, ...restOfProps }) { const [isAuthenticated, setIsAuthenticated] = useState(false); // 新增加载状态,请求未完成时不做跳转判断 const [isLoading, setIsLoading] = useState(true); useEffect(() => { checkLoginStatus() }, []); const checkLoginStatus = () => { axios .get(`${process.env.REACT_APP_API_URL}/session/extend`, { withCredentials: true }) .then(response => { setIsAuthenticated(true); }) .catch((error) => { setIsAuthenticated(false); }) .finally(() => { // 无论请求成功失败,都结束加载状态 setIsLoading(false); }); }; // 加载中状态可以替换为项目通用的加载组件 if (isLoading) return <div>校验登录状态中...</div> return ( <Route {...restOfProps} render={(props) => isAuthenticated ? <Component {...props} /> : <Redirect to="/login" /> } /> ); } export default ProtectedRoute;
逻辑说明
- 组件初始化时先显示加载提示,不执行路由跳转逻辑
- 登录校验请求完成后,更新登录状态和加载状态,触发组件重渲染
- 加载结束后根据最新的登录状态判断是渲染目标页面还是重定向到登录页
内容的提问来源于stack exchange,提问作者Mr. Hankey
相关产品推荐
相关产品推荐

