React Router v6保护路由问题:无法判断历史状态
问题分析与解决方案
你的问题核心是没有正确获取react-router提供的location对象,导致location.key始终为default。以下是具体原因和修正方案:
原因
你通过组件props接收的location和navigate并未被react-router的路由上下文正确注入,react-router v6中必须通过钩子(如useLocation、useNavigate)来获取路由相关的状态和方法,而非直接通过props传递(除非手动在路由配置中传递,但这不是推荐用法)。
修正后的ProtectedRoute组件
import React from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; export const ProtectedRoute = ({ isAuthenticated, children }) => { const location = useLocation(); const navigate = useNavigate(); const hasPreviousState = location.key !== 'default'; if (isAuthenticated) { if (hasPreviousState) { console.log('previous state'); navigate(-1); } else { console.log('no previous state'); navigate('/'); } // 跳转后返回null,避免children不必要的渲染 return null; } return children; };
关键改进点
- 使用
useLocation钩子获取当前路由的location对象,确保拿到正确的location.key值 - 使用
useNavigate钩子获取导航方法,替代props传递的navigate - 认证通过并执行跳转后返回
null,避免先渲染children再跳转的问题
正确使用方式
在路由配置中用ProtectedRoute包裹需要保护的页面(如登录页):
import { Route, Routes } from 'react-router-dom'; import { ProtectedRoute } from './ProtectedRoute'; import LoginPage from './LoginPage'; import HomePage from './HomePage'; function App() { // 替换为你的实际认证状态判断逻辑 const isAuthenticated = localStorage.getItem('token') !== null; return ( <Routes> <Route path="/login" element={ <ProtectedRoute isAuthenticated={isAuthenticated}> <LoginPage /> </ProtectedRoute> } /> <Route path="/" element={<HomePage />} /> </Routes> ); }
验证逻辑
- 当已登录用户从其他页面(如首页)导航到/login时,
location.key不为default,会执行navigate(-1)返回上一页 - 当已登录用户新开标签页直接访问/login时,
location.key为default,会跳转到首页
内容的提问来源于stack exchange,提问作者jeff
相关产品推荐
相关产品推荐

