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

基于React的useRoutes实现受保护路由的代码修正请求

React路由权限控制:实现仅登录用户访问About页面

我创建了一个React应用,使用useRoutes定义了所有路由,包含登录页、注册页、首页及About页面,Demo页面设有导航标签栏。现需要修正代码,实现仅登录用户可访问受保护的About页面,未登录用户访问About时自动跳转至首页。现有代码如下:

现有代码

App.js

import { BrowserRouter as Router, useRoutes } from "react-router-dom";
import { useState } from "react";
import Demo from "./Demo";

function Home() {
  return <div>Home component</div>;
}

function NotFound() {
  return <div>404 Not Found Page</div>;
}

function About() {
  return <div>About Page</div>;
}
function SignIn() {
  return <div>SignIn Page</div>;
}
function LogIn() {
  return <div>LogIn Page</div>;
}
const Routes = () => {
  let routes = useRoutes([
    {
      path: "/",
      element: <Home />,
      children: [
        {
          path: "signin",
          element: <SignIn />,
        },
        {
          path: "login",
          element: <LogIn />,
        },
      ],
    },
    { path: "about/:id", element: <About /> },
    { path: "*", element: <NotFound /> },
  ]);
  return routes;
};
const ProtectedRoute = () => {
  const { token } = useAuth();
  if (!token) {
    return <Navigate to="/login" />;
  }
  return <Outlet />;
};
export default function App() {
  const [login, setLogin] = useState(false);

  return (
    <div className="App">
      <Demo />
      <button onClick={() => setLogin(!login)}>
        {login ? "LogOut" : "LogIn"}
      </button>
      <Router>
        <Routes />
      </Router>
    </div>
  );
}

About.js

import { useNavigate } from "react-router-dom";
import React, { useEffect } from "react";
export default function About({ login }) {
  const navigate = useNavigate();
  useEffect(() => {
    if (!login) {
      navigate("/");
    }
  }, [login, navigate]);
  return <div>About component</div>;
}

Demo.js

import { useNavigate, Link } from "react-router-dom";
export default function Demo() {
  const navigate = useNavigate();

  const onClick = (path) => (e) => {
    e.preventDefault();

    navigate(path);
  };
  return (
    <>
      <ul
        style={{
          display: "flex",
          justifyContent: "space-around",
          listStyle: "none",
        }}
      >
        <li>
          <Link to="/" onClick={onClick("/")}>
            Home
          </Link>
        </li>
        <li>
          <Link to="/about" onClick={onClick("/about")}>
            About
          </Link>
        </li>
      </ul>
    </>
  );
}

修正方案及代码

现有代码存在几个问题:ProtectedRoute引用了不存在的useAuth;Demo组件在Router外部导致Link/useNavigate失效;路由配置未使用ProtectedRoute;About组件的权限判断逻辑冗余。以下是修正后的完整代码:

1. 修正App.js

import { BrowserRouter as Router, useRoutes, Navigate, Outlet } from "react-router-dom";
import { useState, createContext, useContext } from "react";
import Demo from "./Demo";
import About from "./About";

// 创建Auth上下文,传递登录状态
const AuthContext = createContext();

function Home() {
  return <div>Home component</div>;
}

function NotFound() {
  return <div>404 Not Found Page</div>;
}

function SignIn() {
  return <div>SignIn Page</div>;
}

function LogIn() {
  return <div>LogIn Page</div>;
}

// 受保护路由组件:判断登录状态
const ProtectedRoute = () => {
  const { login } = useContext(AuthContext);
  // 未登录则跳转首页
  return login ? <Outlet /> : <Navigate to="/" replace />;
};

const Routes = () => {
  let routes = useRoutes([
    {
      path: "/",
      element: <Home />,
      children: [
        { path: "signin", element: <SignIn /> },
        { path: "login", element: <LogIn /> },
      ],
    },
    // 用ProtectedRoute包裹带参数的About路由
    {
      path: "about/:id",
      element: <ProtectedRoute />,
      children: [{ path: "", element: <About /> }],
    },
    // 用ProtectedRoute包裹默认About路由(对应Demo里的/about)
    {
      path: "about",
      element: <ProtectedRoute />,
      children: [{ path: "", element: <About /> }],
    },
    { path: "*", element: <NotFound /> },
  ]);
  return routes;
};

export default function App() {
  const [login, setLogin] = useState(false);

  return (
    <AuthContext.Provider value={{ login }}>
      <div className="App">
        {/* Demo移到Router内部,确保Link/useNavigate生效 */}
        <Router>
          <Demo />
          <button onClick={() => setLogin(!login)}>
            {login ? "LogOut" : "LogIn"}
          </button>
          <Routes />
        </Router>
      </div>
    </AuthContext.Provider>
  );
}

2. 简化About.js

不需要在组件内部判断权限,交给ProtectedRoute处理:

export default function About() {
  return <div>About component</div>;
}

3. 简化Demo.js

去掉冗余的onClick,Link本身已经具备跳转功能:

import { Link } from "react-router-dom";
export default function Demo() {
  return (
    <>
      <ul
        style={{
          display: "flex",
          justifyContent: "space-around",
          listStyle: "none",
        }}
      >
        <li><Link to="/">Home</Link></li>
        <li><Link to="/about">About</Link></li>
      </ul>
    </>
  );
}

核心改动说明

  • 创建AuthContext传递登录状态,让ProtectedRoute能获取登录状态
  • 修正ProtectedRoute逻辑,未登录时跳转首页
  • 将Demo组件移到Router内部,确保路由相关钩子/组件正常工作
  • 用ProtectedRoute包裹About路由,统一控制权限
  • 简化About和Demo组件的冗余代码

内容的提问来源于stack exchange,提问作者Sougata Mukherjee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:14:55