React Router条件路由页面刷新时总是重定向,如何保留当前路由?
问题解决方法
核心原因
刷新页面时,user初始状态是空对象{},此时user?.email为undefined,会立刻触发重定向到/login;等useEffect从localStorage加载完用户信息后,又会从/login重定向到/,直接把原来的访问路由覆盖了。
解决方案
1. 调整状态初始值与加载逻辑
把user初始状态设为null,加个加载状态避免初始阶段的错误跳转:
const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const theUser = localStorage.getItem("user"); if (theUser && theUser !== "undefined") { setUser(JSON.parse(theUser)); } setLoading(false); // 标记加载完成 }, []); // 加载中可以显示空白或简单的加载动画 if (loading) { return <div>加载中...</div>; }
2. 封装统一的受保护路由组件
写一个ProtectedRoute组件,把校验逻辑抽离出来,同时保留当前访问路径:
function ProtectedRoute({ children }) { const user = JSON.parse(localStorage.getItem("user")); const location = useLocation(); if (!user?.email) { // 重定向到登录页,把当前路径存在state里,后续登录后能跳回来 return <Navigate to="/login" state={{ from: location }} replace />; } return children; }
3. 重构路由配置
用ProtectedRoute包裹需要校验权限的页面,简化路由代码:
// App组件内的Routes部分 <Routes> <Route path="/login" element={<Login />} /> <Route path="/" element={ <ProtectedRoute> <Home user={user} /> </ProtectedRoute> } /> <Route path="/feedback" element={ <ProtectedRoute> <Feedback user={user} /> </ProtectedRoute> } /> <Route path="/candidates" element={ <ProtectedRoute> <Candidates user={user} /> </ProtectedRoute> } /> <Route path="/view-feedback" element={ <ProtectedRoute> <ViewFeedback user={user} /> </ProtectedRoute> } /> </Routes>
4. 登录页处理跳转逻辑
登录成功后,读取之前存在state里的路径,跳回用户原本要访问的页面:
// Login组件示例 const navigate = useNavigate(); const location = useLocation(); const handleLogin = () => { // 假设登录成功后拿到了用户信息 const loggedInUser = { email: "xxx@xxx.com", ... }; localStorage.setItem("user", JSON.stringify(loggedInUser)); // 优先跳回之前的页面,默认跳首页 const from = location.state?.from?.pathname || "/"; navigate(from, { replace: true }); };
额外优化点
- 直接在
ProtectedRoute里读取localStorage,不用依赖组件状态的异步更新,减少状态不同步的问题。 - 用
replace属性替换历史记录,避免用户点击返回按钮时回到登录页。
内容的提问来源于stack exchange,提问作者Steven Werner
相关产品推荐
相关产品推荐

