基于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
相关产品推荐
相关产品推荐

