如何实现已登录用户访问登录页时重定向至首页并解决路由导航冲突?
解决React Router中ProtectedRoute与RestrictedPublicRoute的导航冲突问题
这个问题的核心是登录完成后,RestrictedPublicRoute的重定向逻辑会抢先触发,覆盖Login组件中跳回原路径的操作。我们只需要给RestrictedPublicRoute加一个判断条件,区分用户是主动访问登录页还是从受保护路由跳转过来登录的场景即可。
调整RestrictedPublicRoute组件逻辑
修改RestrictedPublicRoute,让它只在用户主动访问登录页(没有携带from跳转来源)时,才执行重定向到首页的操作。如果用户是从受保护路由跳过来的(location.state.from存在),则允许Login组件继续渲染,完成跳回原路径的操作:
export const RestrictedPublicRoute = () => { const { token } = useAuth(); const location = useLocation(); if (token) { // 只有当用户主动访问登录页(无跳转来源)时,才重定向到首页 if (!location.state?.from) { return <Navigate to="/" replace />; } } // 未登录 或 从受保护路由跳转过来的已登录用户,都渲染子路由(Login组件) return <Outlet />; };
优化Login组件的跳转逻辑
同时,确保Login组件在登录成功后,正确跳转到原路径并替换当前历史记录,避免用户回退到登录页:
// Login组件示例 import { useNavigate, useLocation } from 'react-router-dom'; import { useAuth } from './auth-context'; export const Login = () => { const navigate = useNavigate(); const location = useLocation(); const { setToken } = useAuth(); const handleLogin = async (credentials) => { // 模拟登录请求 const token = await fetch('/api/login', { method: 'POST', body: JSON.stringify(credentials) }).then(res => res.json()); setToken(token); // 获取原路径,默认跳首页 const origin = location.state?.from?.pathname || '/'; // 替换当前历史记录,避免回退到登录页 navigate(origin, { replace: true }); }; return ( <div> {/* 登录表单 */} <button onClick={() => handleLogin({ username: 'test', password: 'test' })}> 登录 </button> </div> ); };
为什么这样能解决冲突?
- 当未登录用户访问受保护路由时,
ProtectedRoute会跳转到/login并携带from参数,此时RestrictedPublicRoute检测到location.state.from存在,即使登录后token生成,也不会触发重定向,而是让Login组件完成跳回原路径的操作。 - 当已登录用户主动访问
/login(比如地址栏输入、从其他公共页跳转),location.state.from不存在,RestrictedPublicRoute会立即重定向到首页,符合需求。
内容的提问来源于stack exchange,提问作者vance
相关产品推荐
相关产品推荐

