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

React Router Dom中useEffect执行前触发路由重定向问题

问题根源
  • React 执行顺序固定:组件首次挂载渲染完成后,才会执行useEffect内的副作用逻辑,当前写法等接口发起请求时,首次渲染已经走完。
  • 仅用boolean类型的token状态无法覆盖三种场景:鉴权校验中、校验通过、校验不通过。初始值设为false会直接命中未登录重定向逻辑,哪怕后续接口返回有效鉴权结果,已经触发的跳转也不会自动回退。
  • 附带小问题:Express 端用res.send(true)返回的是text/plain格式响应,前端调用res.json()解析时可能抛出格式错误,建议返回标准JSON格式。
修复实现

后端接口调整

app.post('/refresh_token_from_db', async (req: Request, res: Response) => {
    // 改用json方法返回标准JSON格式,匹配前端解析逻辑
    res.json(true)
})

路由守卫组件调整

核心是新增加载状态,拦截首次渲染时的跳转逻辑,等鉴权结果返回后再做路由判断:

import { Navigate, Outlet } from 'react-router-dom'
import { useState, useEffect } from 'react';

function ProtectedRoutes() {
    const [token, setToken] = useState<boolean>(false);
    // 初始设为加载中状态,避免首次渲染直接触发跳转
    const [isAuthChecking, setIsAuthChecking] = useState<boolean>(true);

    useEffect(() => {
        const checkTokenValid = async () => {
            try {
                const res = await fetch('/refresh_token_from_db', {
                    method: 'POST',
                    mode: 'same-origin',
                    redirect: 'follow',
                    credentials: 'same-origin',
                    headers: {
                        'content-type': 'application/json',
                        'Accept': 'application/json'
                    },
                });
                const authResult = await res.json();
                setToken(authResult);
            } catch (err) {
                console.error('鉴权请求异常:', err);
                setToken(false);
            } finally {
                // 请求完成(无论成功失败)结束加载状态
                setIsAuthChecking(false);
            }
        }
        checkTokenValid();
    }, []);

    // 鉴权未完成时,展示加载占位,不执行路由判断
    if (isAuthChecking) {
        return <div>权限校验中...</div>
    }

    // 鉴权完成后再根据结果选择渲染受保护路由或跳转登录
    return token ? <Outlet /> : <Navigate to="/login" replace />;
}

export default ProtectedRoutes
关键逻辑说明
  • 拆分isAuthChecking状态专门标记鉴权请求进度,首次渲染时不会命中跳转逻辑
  • 接口请求过程中展示轻量加载提示,避免页面空白
  • finally块统一处理加载状态收尾,不管请求成功、失败都不会卡在加载页
  • 给Navigate组件加上replace属性,替换当前路由栈记录,避免用户点击浏览器返回键时陷入鉴权判断的死循环

内容的提问来源于stack exchange,提问作者Owen Delisle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:45:46