直接访问React-Router路由自动跳转至根路径问题排查求助
问题分析与解决
核心原因
页面刷新时,AuthContext的isLogged初始值为false,且loading初始值错误设为false,导致PrivateRoute在token验证请求完成前,就判定未登录并执行跳转。而通过按钮跳转时,AuthContext已经完成初始化,isLogged状态正确,所以路由正常。
修复步骤
1. 修正AuthContext的loading初始值
将loading的初始状态设为true,确保页面加载时先处于加载状态,直到token验证完成:
export function AuthProvider({children}) { // 初始loading设为true,代表正在验证token const [isLogged, setIsLogged] = useState(false); const [loading, setLoading] = useState(true); useEffect(() => { async function checkToken() { const token = JSON.parse(localStorage.getItem('costs_token')); if (!token) return false; const headers = { 'Content-Type': 'application/json', authorization: 'Bearer '+token } const response = await fetch('/auth/validatetoken', { method: 'GET', headers }); if (response.status === 200) { setIsLogged(true); return true; } localStorage.removeItem('costs_token'); return false; } checkToken().then(() => setLoading(false)); }, []); return ( <AuthContext.Provider value={{isLogged, loading}}> {children} </AuthContext.Provider> ); }
2. 优化PrivateRoute组件
让PrivateRoute直接从AuthContext获取状态,无需手动传入condition,减少冗余:
function PrivateRoute({ redirectRoute = '/login' }) { const { isLogged, loading } = useAuth(); if(loading) return null; // 加载中时不渲染任何内容,避免提前跳转 return isLogged ? <Outlet /> : <Navigate to={redirectRoute} replace />; }
3. 简化路由结构
React Router v6中exact已不再需要,路由嵌套可以更简洁:
function Router() { return ( <BrowserRouter> <Routes> {/* 私有路由组 */} <Route element={<PrivateRoute />}> <Route path="/" element={<Home />} /> <Route path="/projects" element={<Projetos />} /> </Route> {/* 其他公开路由,比如登录页 */} <Route path="/login" element={<Login />} /> </Routes> </BrowserRouter> ); }
额外注意点
- 确保
AuthProvider包裹在BrowserRouter外层,保证路由能获取到AuthContext的状态。 - 在
Navigate组件中添加replace属性,避免跳转后浏览器历史记录中保留原路由,防止用户点击后退回到未授权页面。
内容的提问来源于stack exchange,提问作者Guilherme Kauã
相关产品推荐
相关产品推荐

