React路由从v5升级到v6后出现404及用户认证异常问题求助
React Router v5 升级v6后受保护路由异常问题
最近将React路由从v5升级到v6,已参考升级方案适配,但仍存在问题,怀疑根源在于受保护路由(ProtectedRoute)组件。
登录操作可正常完成,但浏览器无法识别已登录用户,该用户存在于数据库中,且通过Insomnia调用后端接口可正常登录。
相关代码
v5版本ProtectedRoute组件
const ProtectedRoute = () => { const location = useLocation(); const user = useSelector((state) => state.user); useEffect(() => { if (!user.isAuthenticated && !user.pending) navigate("/"); }); return ( <Route {...rest} render={(props) => { if (user.isAuthenticated && !user.pending) { return <Component {...props} />; } else return <LoadingScreen />; }} /> ); }; export default ProtectedRoute;
v6版本ProtectedRoute组件
import React, { useEffect } from "react"; import { useSelector } from "react-redux"; import { Navigate, Outlet, useLocation } from "react-router-dom"; import LoadingScreen from "../components/LoadingScreen"; const ProtectedRoute = ({children}) => { const {isAuthenticated, pending} = useSelector((state) => state.user); if (pending) return null; return isAuthenticated ? children : <Navigate to= "/" replace /> }; export default ProtectedRoute;
App.js路由配置
const App = () => { useEffect(() => { loadUser(Store.dispatch); }, []); return ( <BrowserRouter> <Alert /> <Routes> <Route path="/board" element={<ProtectedRoute><Boards /></ProtectedRoute>} /> <Route path="/board/:id" element={<ProtectedRoute><Board /></ProtectedRoute>} /> <Route path="/login" element={<FreeRoute><Login /></FreeRoute>} /> <Route path="/register" element={<FreeRoute><Register /></FreeRoute>} /> <Route path="/" element={<FreeRoute><Index /></FreeRoute>} /> </Routes> </BrowserRouter> ); };
错误截图

问题分析与修复
核心问题点
- 加载状态处理错误:原v6代码中
pending为true时返回null,导致组件渲染为空,此时isAuthenticated可能还未完成更新,直接触发跳转逻辑,误判用户未登录。 - 跳转目标错误:未认证时跳转到首页,而非登录页,不符合受保护路由的逻辑,也导致用户登录后无法回到目标页面。
修复后的ProtectedRoute组件
import React from "react"; import { useSelector } from "react-redux"; import { Navigate, useLocation } from "react-router-dom"; import LoadingScreen from "../components/LoadingScreen"; const ProtectedRoute = ({ children }) => { const { isAuthenticated, pending } = useSelector((state) => state.user); const location = useLocation(); // 加载中显示LoadingScreen,等待状态更新完成 if (pending) return <LoadingScreen />; // 未认证则跳转到登录页,记录当前位置方便登录后返回 return isAuthenticated ? ( children ) : ( <Navigate to="/login" replace state={{ from: location }} /> ); }; export default ProtectedRoute;
额外检查点
- Redux状态更新:确认登录接口调用成功后,
isAuthenticated是否被正确设置为true,pending是否设为false;loadUser接口完成后也要同步更新这些状态。 - FreeRoute组件逻辑:如果
FreeRoute是限制已登录用户访问的路由(如登录/注册页),需确保其逻辑正确,避免登录后仍能进入这些页面。
内容的提问来源于stack exchange,提问作者User
相关产品推荐
相关产品推荐

