React Router DOM v6问题:直接输入URL访问私有路由自动重定向至首页
解决React私有路由直接访问URL自动跳转到首页的问题
问题描述
在React项目中配置私有路由与公共路由时,直接输入带路径的URL(如https://localhost:3000/dashboard),页面会自动重定向到首页https://localhost:3000/,怀疑是PrivateRoutes函数导致,但不确定修改方式。
现有代码
App.js
const App = () => { const { state: { isAuthenticated }, } = AuthContext(); function PrivateRoutes() { return isAuthenticated ? <Outlet /> : <Navigate to="/login" />; } function PublicRoutes() { return isAuthenticated ? <Navigate to="/home" /> : <Outlet />; } return ( <BrowserRouter> <Routes> <Route element={<PrivateRoutes />}> <Route path="/*" element={<Layout />} /> </Route> <Route path="*" element={<Error />} /> <Route path="login" element={<PublicRoutes />}> <Route path="/login" element={<Login />} /> </Route> </Routes> </BrowserRouter> ); };
Layout.js
const Layout = () => { return ( <Box> <Header /> <Routes> <Route index element={<Home />} /> <Route path="dashboard" element={<Dashboard />} /> <Route path="transaction" element={<Transaction />} /> <Route path='/*' element={<Navigate to="/" />} /> </Routes> <Footer /> </Box> ); };
问题原因
页面刷新时,AuthContext的isAuthenticated初始状态为false,导致PrivateRoutes先跳转到/login;等认证状态从本地存储/API加载完成后,PublicRoutes检测到用户已认证,又跳转到首页(/home对应Layout的index路由),最终表现为直接跳转到首页。此外,路由顺序不合理,Error路由会拦截后续的login路由匹配。
解决方案
1. 给AuthContext添加加载状态
在AuthContext中增加isLoading状态,用于标识认证状态是否正在加载:
// AuthContext.js示例 import { createContext, useState, useEffect } from 'react'; const AuthContext = createContext(); export const AuthProvider = ({ children }) => { const [state, setState] = useState({ isAuthenticated: false, isLoading: true // 初始为加载中 }); useEffect(() => { // 从本地存储获取认证状态(或调用API验证) const authToken = localStorage.getItem('authToken'); setState(prev => ({ ...prev, isAuthenticated: !!authToken, isLoading: false })); }, []); return ( <AuthContext.Provider value={{ state }}> {children} </AuthContext.Provider> ); };
2. 修改PrivateRoutes和PublicRoutes
在加载状态下不执行重定向,避免中间跳转:
const App = () => { const { state: { isAuthenticated, isLoading }, } = AuthContext(); function PrivateRoutes() { if (isLoading) { return <div>加载中...</div>; // 可替换为自定义加载组件 } return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />; } function PublicRoutes() { if (isLoading) { return <div>加载中...</div>; } return isAuthenticated ? <Navigate to="/" replace /> : <Outlet />; } // ...后续代码 };
3. 调整路由顺序
将login路由放在Error路由之前,避免被兜底路由拦截:
return ( <BrowserRouter> <Routes> {/* 私有路由 */} <Route element={<PrivateRoutes />}> <Route path="/*" element={<Layout />} /> </Route> {/* 登录路由 - 放在Error路由前 */} <Route path="login" element={<PublicRoutes />}> <Route index element={<Login />} /> {/* 用index简化路径配置 */} </Route> {/* 兜底错误路由 */} <Route path="*" element={<Error />} /> </Routes> </BrowserRouter> );
4. 优化Layout路由(可选)
将Layout中的兜底路由路径改为*,符合React Router规范:
<Routes> <Route index element={<Home />} /> <Route path="dashboard" element={<Dashboard />} /> <Route path="transaction" element={<Transaction />} /> <Route path="*" element={<Navigate to="/" replace />} /> </Routes>
内容的提问来源于stack exchange,提问作者Hazel
相关产品推荐
相关产品推荐

