You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中使用useRoutes钩子实现私有路由?

React useRoutes 实现私有/公开路由的逻辑拆解与优化

现有代码的逻辑分析

先拆解你当前的实现逻辑:

  1. 通过useContext(AuthContext)获取全局共享的登录状态isAuth,这是权限判断的核心依据
  2. 定义路由数组routes,其中只有根路径/做了权限校验:已登录渲染<Home />,未登录则通过<Navigate />跳转到登录页
  3. /printers、/items、/login这几个路由没有权限控制,属于公开可访问状态
  4. 调用useRoutes(routes)生成路由实例并返回,完成路由渲染

但这个写法存在两个问题:一是需要保护的路由(比如/printers)未做权限校验,未登录用户也能直接访问;二是每个私有路由都要写三元运算符,代码重复且不易维护。

私有路由的核心原理

私有路由本质是路由守卫:在渲染目标组件前先拦截,检查用户的登录状态:

  • 已登录:正常渲染目标组件
  • 未登录:跳转到登录页,同时可以记录当前访问路径,方便登录后跳转回原页面

优化后的实现方案

我们可以封装一个通用的PrivateRoute组件,把权限判断逻辑抽离出来,所有需要保护的路由都复用这个组件:

1. 封装私有路由组件

import { Navigate } from "react-router-dom";
import { useContext } from "react";
import { AuthContext } from "../contexts";

function PrivateRoute({ children }) {
  const { sessionContextValue } = useContext(AuthContext);
  const { isAuth } = sessionContextValue;

  // 未登录时跳转到登录页,同时记录当前访问路径
  if (!isAuth) {
    return <Navigate to="/login" replace state={{ from: window.location.pathname }} />;
  }

  // 已登录则渲染目标组件
  return children;
}

export default PrivateRoute;

2. 重构Routes组件

用PrivateRoute包裹所有需要保护的路由,公开路由直接渲染即可:

import Home from "../pages/home"
import Items from "../pages/itens"
import Login from "../pages/login"
import Printers from "../pages/printers"
import { useRoutes } from "react-router-dom"
import PrivateRoute from "./PrivateRoute";

function Routes() {
    const routes = [
        {
            path: '/',
            element: (
                <PrivateRoute>
                    <Home />
                </PrivateRoute>
            ),
        },
        {
            path: '/printers',
            element: (
                <PrivateRoute>
                    <Printers />
                </PrivateRoute>
            )
        },
        {
            path: '/items',
            element: (
                <PrivateRoute>
                    <Items />
                </PrivateRoute>
            )
        },
        {
            path: '/login',
            element: <Login />
        }
    ]

    return useRoutes(routes)
}

export default Routes

关键细节解释

  • PrivateRoute复用性:把权限判断逻辑抽离后,所有需要保护的路由只需要用PrivateRoute包裹,避免重复代码,后续修改权限规则只需改这一个组件
  • Navigate的replace属性:使用replace而非push,是为了避免在浏览器历史记录中留下未登录时的访问痕迹,用户登录后返回不会再回到未授权页面
  • state传递原路径:跳转到登录页时,通过state记录用户原本访问的路径,登录成功后可以从state中取出路径跳转回去,提升体验(示例:在Login组件中获取原路径):
    import { useNavigate, useLocation } from "react-router-dom";
    
    function Login() {
      const navigate = useNavigate();
      const location = useLocation();
      // 取原路径,默认跳首页
      const from = location.state?.from || '/';
    
      // 登录成功后执行跳转
      const handleLogin = () => {
        // ...登录逻辑
        navigate(from, { replace: true });
      }
    
      return <div>登录组件</div>
    }
    
  • 公开路由的反向处理:如果需要避免已登录用户访问登录页,可以给/login路由加反向判断:
    {
        path: '/login',
        element: isAuth ? <Navigate to="/" replace /> : <Login />
    }
    

内容的提问来源于stack exchange,提问作者Bruno Bispo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 14:10:29