React自定义ProtectedRoute组件未渲染、token校验逻辑失效问题排查
问题根因排查与解决方案
1. 核心错误:违反React Router v6的路由声明规则
React Router v6要求所有<Route>组件必须是<Routes>组件的直接子节点,不能包裹在自定义组件内部。你当前的实现把<Route>放在ProtectedRoute的返回值中,再将<ProtectedRoute>作为<Routes>的子节点,会导致路由系统根本识别不到你在ProtectedRoute内声明的路由规则,ProtectedRoute本身也不会被路由逻辑触发执行,这就是为什么你看不到console输出、修改ProtectedRoute返回值完全不生效的核心原因。
你能正常访问受保护路径,大概率是你的App.tsx中存在冗余的路由声明,直接匹配到了对应路径,完全绕开了你写的鉴权逻辑。
2. 正确的ProtectedRoute实现方式
React Router v6的路由鉴权组件应该作为受保护页面的包装层,而非<Route>的包装层,参考实现如下:
// ProtectedRoute.tsx import { Navigate } from 'react-router-dom'; import { useState, useLayoutEffect } from 'react'; import axios from 'axios'; const ProtectedRoute = ({ children }: { children: React.ReactNode }) => { // 初始设为null表示校验中,避免未完成校验时错误跳转 const [hasValidToken, setHasValidToken] = useState<boolean | null>(null); useLayoutEffect(() => { axios .get('http://localhost:5000/authorization', { withCredentials: true, }) .then((response) => { setHasValidToken(true); console.log('valid token!'); }) .catch((error) => { if (error.response?.data?.message) { console.error(error.response.data.message); } else { console.error(`Error: ${error}`); } setHasValidToken(false); }); }, []); // 校验中返回加载态 if (hasValidToken === null) return <div>加载中...</div>; return hasValidToken ? children : <Navigate to="/login" replace />; }; export default ProtectedRoute;
3. 路由配置调整
你遍历路由配置生成路由的逻辑需要修改为以下形式,将受保护的页面组件传入ProtectedRoute的children:
// App.tsx 中的路由声明部分 import { Routes, Route } from 'react-router-dom'; import ProtectedRoute from './common/components/ProtectedRoute'; import protectedRoutes from './config/protectedRoutes'; // 其他页面组件导入省略 function App() { return ( <Routes> {/* 公共路由直接声明 */} <Route path="/login" element={<Login />} /> {/* 受保护路由遍历生成 */} {protectedRoutes.map((route) => ( <Route key={route.path} path={route.path} element={ <ProtectedRoute> {route.element} </ProtectedRoute> } /> ))} </Routes> ); }
4. 额外注意事项
- 先检查App.tsx中是否有重复的路由声明,删除和受保护路径重合的冗余Route配置,避免绕开鉴权
- 跳转登录页时添加
replace属性,避免用户点击后退按钮回到鉴权页出现循环跳转 - 如果需要适配路由切换时重新校验权限,可以把当前路由路径加入
useLayoutEffect的依赖数组
内容的提问来源于stack exchange,提问作者Kaho
相关产品推荐
相关产品推荐

