React Router实现已登录用户禁止访问登录页的问题
问题解决:已登录用户访问登录页自动重定向首页
问题现状
已认证用户访问 /login 页面时,仍能正常进入登录页,无法自动跳转到首页。尝试修改 PrivateRoute 组件后问题未解决。
问题原因
- 当前
/login路由未挂载任何路由守卫组件,直接渲染Login组件,导致已登录用户无拦截逻辑 - 修改后的
PrivateRoute逻辑顺序错误:先判断user?.email存在就返回children,后续判断已登录且路径为/login的代码永远不会执行
解决方案
方案1:创建公共路由守卫(推荐)
新增一个 PublicRoute 组件,专门处理已登录用户禁止访问的公开页面(如登录、注册页):
// PublicRoute.jsx import { useContext } from "react"; import { AuthContext } from "../providers/AuthProvider"; import { Navigate, useLocation } from "react-router-dom"; const PublicRoute = ({ children }) => { const { user, loading } = useContext(AuthContext); const location = useLocation(); if (loading) { return <progress className="progress w-full"></progress>; } // 已登录用户访问登录/注册页,直接重定向到首页 if (user?.email && (location.pathname === "/login" || location.pathname === "/signup")) { return <Navigate to="/" replace />; } return children; }; export default PublicRoute;
在路由配置中,给 /login 和 /signup 路由挂载这个组件:
// route.jsx // 导入新增的PublicRoute import PublicRoute from "./PublicRoute"; const router = createBrowserRouter([ { path: "/", element: <Main></Main>, children: [ { path: "/", element: <Home></Home>, }, { path: "/login", element: ( <PublicRoute> <Login></Login> </PublicRoute> ), }, { path: "/signup", element: ( <PublicRoute> <SignUp></SignUp> </PublicRoute> ), }, // 其他私有路由保持不变 { path: "/bookings", element: ( <PrivateRoute> <Bookings></Bookings> </PrivateRoute> ), }, { path: "/services/:id", element: <PrivateRoute><Checkout></Checkout></PrivateRoute>, loader: ({ params }) => fetch(`http://localhost:5000/services/${params.id}`), }, ], }, ]);
方案2:直接在Login组件内处理重定向
如果不想新增组件,可以在 Login 组件内部判断用户状态:
// Login.jsx import { useContext } from "react"; import { AuthContext } from "../providers/AuthProvider"; import { Navigate } from "react-router-dom"; const Login = () => { const { user, loading } = useContext(AuthContext); if (loading) { return <progress className="progress w-full"></progress>; } // 已登录直接重定向 if (user?.email) { return <Navigate to="/" replace />; } // 原登录页面逻辑 return ( // ...你的登录表单代码 ); }; export default Login;
说明
方案1更符合路由守卫的职责分离原则,将路由权限逻辑集中在守卫组件中,便于维护和扩展;方案2适合快速修改,逻辑直接在页面组件内处理。
内容的提问来源于stack exchange,提问作者Ishrak Abir
相关产品推荐
相关产品推荐

