React中axios GET请求返回后useState状态未更新该如何解决?
问题原因及修复方案
1. 打印值为false是闭包+异步更新的正常表现
React的状态更新是异步批量执行的,且你在checkAuth函数中访问的isValidated是组件首次渲染时闭包捕获的初始值(固定为false)。就算调用了setIsValidated(true),本次函数执行上下文内的isValidated还是旧值,所以两处打印都会返回false,这并不代表状态没有触发更新。
如果你要验证状态是否更新,可以在组件函数的最顶层添加打印:console.log('组件渲染,isValidated值为:', isValidated),就能看到状态更新后组件重新渲染时的最新值。
2. 状态更新不生效的核心原因:组件提前被重定向卸载
你当前的渲染逻辑是只要isValidated为false就直接触发重定向到首页,而鉴权请求是异步发起的,请求返回前isValidated始终是初始值false,组件会立刻触发重定向、从路由中卸载。等请求成功调用setIsValidated的时候,组件已经被销毁了,状态更新自然不会生效。
你需要新增一个加载状态,请求未完成时展示加载UI,不要直接重定向,修复后的代码如下:
import React from "react"; import { Redirect, Route } from "react-router-dom"; import { useState, useEffect } from "react"; // 补充缺失的axios引入 import axios from "axios"; const ProtectedRoute = ({ component: Component, ...restOfProps }) => { const [isValidated, setIsValidated] = useState(false); // 新增加载状态,控制请求期间的展示逻辑 const [authLoading, setAuthLoading] = useState(true); let token = localStorage.getItem("Authorization"); let config = { headers: { authorization: token, }, }; const checkAuth = async () => { // 无token直接跳过请求,标记鉴权失败 if (!token) { setAuthLoading(false); return; } try { const res = await axios.get("http://localhost:3001/checkAuth", config) if (res.status === 201) { setIsValidated(true); } } catch (err) { console.log(err); } finally { // 请求完成后关闭加载态 setAuthLoading(false); } }; useEffect(() => { checkAuth(); }, []); // 鉴权请求未完成时展示加载状态,避免提前重定向 if (authLoading) return <div>鉴权校验中,请稍候...</div> return ( <Route {...restOfProps} render={(props) => isValidated ? <Component {...props} /> : <Redirect to="/" /> } /> ); }; export default ProtectedRoute;
额外优化点
你原来的代码混用了await和.then的写法,统一用async/await+try/catch的写法逻辑更清晰,也更容易维护。
内容的提问来源于stack exchange,提问作者Stark
相关产品推荐
相关产品推荐

