MERN应用中useNavigate()刷新页面后登录跳转失效问题
问题原因
刷新页面后登录无法跳转首页的核心问题是路由守卫没有响应localStorage的token变化:
- 原代码里的
PrivateRoute是普通函数,仅在App组件初始渲染时执行一次。刷新页面后,App初始渲染时localStorage无token,路由判断结果为false,默认指向/login。 - 登录成功后虽然把token存入localStorage,但App组件不会重新触发渲染,路由守卫的判断逻辑仍停留在初始状态,导致调用
navigate("/")后,立刻被路由守卫跳回/login页面。
解决方案
将路由守卫改为响应token变化的React组件,使用状态监听localStorage的更新,同时遵循React Router的官方私有路由实现方式:
修改App.js
import { Navigate, Outlet } from 'react-router-dom'; import { useState, useEffect } from 'react'; // 改写为带状态的私有路由组件 const ProtectedRoute = () => { // 初始化状态为当前localStorage中是否有token const [hasValidToken, setHasValidToken] = useState(!!localStorage.getItem('jwt')); useEffect(() => { // 监听localStorage变化,同步token状态 const handleStorageUpdate = () => { setHasValidToken(!!localStorage.getItem('jwt')); }; window.addEventListener('storage', handleStorageUpdate); // 组件卸载时移除监听 return () => window.removeEventListener('storage', handleStorageUpdate); }, []); // 有token则渲染受保护页面,否则跳转到登录页 return hasValidToken ? <Outlet /> : <Navigate replace to="/login" />; }; function App() { return ( <Router> <Navbar /> <Routes> {/* 用ProtectedRoute包裹所有需要权限的路由 */} <Route element={<ProtectedRoute />}> <Route path="/" element={<Home />} /> </Route> <Route path="/login" element={<Login />} /> <Route path="/register" element={<Register />} /> </Routes> </Router> ); }
额外优化建议
- 确认Login.js中token的解构逻辑:如果后端返回的是
res.data.token(而非res.data.token.token),需要修正为const token = res.data.token;,避免因解构错误导致token未正确存入localStorage。 - 可在Login的handleSubmit中添加错误提示,比如当后端返回登录失败时,给用户显示对应的错误信息,提升体验。
内容的提问来源于stack exchange,提问作者EddyIT
相关产品推荐
相关产品推荐

