React Router Dom v6已认证用户仍被重定向至登录路由求助
问题根源
你的PrivateRoute会把已认证用户重定向到登录页,核心原因是组件初始化时的状态更新时机不匹配:
- App组件挂载时,
isAuth初始值是false,PrivateRoute会立刻触发重定向 - 读取localStorage认证信息的useEffect是在组件挂载后才执行,等
isAuth被更新为true时,重定向已经完成了
另外,你原来的useEffect依赖authState.isAuth,会导致每次isAuth变化都重复执行认证检查,完全没必要,还可能引发不必要的状态循环。
解决方案
1. 新增加载状态,避免过早重定向
在App的authState里加入isLoading状态,在认证状态未确定前,不触发重定向也不渲染受保护内容。
2. 修正useEffect依赖项
把useEffect的依赖改成空数组,确保只在组件挂载时执行一次认证检查。
修改后的代码
App.js关键部分修改
function App(props) { const navigate = useNavigate(); // 新增isLoading状态,初始为true const [authState, setAuthState] = useState({ isAuth: false, token: null, userId: null, isLoading: true, }); const [showNav, setShowNav] = useState(true); // 依赖项改为空数组,只在组件挂载时执行一次 useEffect(() => { if (window.location.href.includes("admin")) { setShowNav(false); } const token = localStorage.getItem("token"); const expiryDate = localStorage.getItem("expiryDate"); // 没有token或过期,直接设置加载完成 if (!token || !expiryDate) { setAuthState(prev => ({ ...prev, isLoading: false })); return; } const userId = localStorage.getItem("userId"); const remainingMilliseconds = new Date(expiryDate).getTime() - new Date().getTime(); // 检查token是否过期 if (remainingMilliseconds <= 0) { logoutHandler(); setAuthState(prev => ({...prev, isLoading: false})); return; } setAuthState((prevState) => { return { ...prevState, isAuth: true, token: token, userId: userId, isLoading: false, // 加载完成,更新状态 }; }); setAutoLogout(remainingMilliseconds); }, []); // 移除authState.isAuth依赖 // ... 其他函数保持不变 return ( <div className="App"> {showNav && ( <Nav token={authState.token} isAuth={authState.isAuth} onLogout={logoutHandler} /> )} <Routes> {/* ... 其他路由保持不变 */} <Route path="/orders" element={ <PrivateRoute {...authState}> <Orders token={authState.token} /> </PrivateRoute> } /> {/* ... 其他路由保持不变 */} </Routes> </div> ); }
PrivateRoute.js修改
const PrivateRoute = (props) => { // 加载状态时,渲染加载提示(可以换成你自己的加载组件) if (props.isLoading) { return <div>加载中...</div>; } if (!props.isAuth) { return <Navigate to="/login" replace />; } return props.children; }; export default PrivateRoute;
额外注意事项
- 登录成功后,不需要手动设置
isLoading,因为初始挂载时的useEffect已经把它设为false了 - 自动登出逻辑里,也要确保
isLoading不会被错误设置 - 加载提示可以换成更友好的UI组件,比如Spinner
内容的提问来源于stack exchange,提问作者Rohan Rana Magar
相关产品推荐
相关产品推荐

