React Router 6自定义受保护路由:替代Redirect的实现方案
React Router 6 受保护路由实现修正
错误原因
React Router 6 对 <Routes> 的子组件有严格要求:只能是 <Route> 或 <React.Fragment>,不能直接放置自定义组件。同时RR6移除了Route的component、render props,统一改用element属性传递组件。
步骤1:修正App.js的路由配置
把原来的component替换为element,并将ProtectedRoutes作为<Route>的element值传入,而非直接作为Route组件使用:
function App() { return ( <Container> <Row> <Col className="text-center"> <h1>React Authentication Tutorial</h1> <section id="navigation"> <a href="/">Home</a> <a href="/free">Free Component</a> <a href="/auth">Auth Component</a> </section> </Col> </Row> <Routes> <Route path="/" element={<Account />} /> <Route path="/free" element={<FreeComponent />} /> {/* 将ProtectedRoutes作为element传入,内部包裹需要保护的组件 */} <Route path="/auth" element={ <ProtectedRoutes> <AuthComponent /> </ProtectedRoutes> } /> </Routes> </Container> ); }
步骤2:重写ProtectedRoutes组件
RR6中不再使用render或component props,而是通过组件嵌套+useLocation钩子获取当前路由信息,同时用Navigate替代Redirect:
import React from "react"; import { Navigate, useLocation } from "react-router-dom"; import Cookies from "universal-cookie"; const cookies = new Cookies(); export default function ProtectedRoutes({ children }) { const location = useLocation(); const token = cookies.get("TOKEN"); if (token) { // 已登录,渲染受保护的子组件 return children; } else { // 未登录,重定向到首页,并记录原本要访问的路径 return ( <Navigate to="/" replace state={{ from: location }} /> ); } }
额外优化建议
- 把导航栏的
<a>标签替换为RR6的<Link>组件,避免页面整体刷新:import { Link } from "react-router-dom"; // 替换后 <section id="navigation"> <Link to="/">Home</Link> <Link to="/free">Free Component</Link> <Link to="/auth">Auth Component</Link> </section> - 如果需要批量保护多个路由,可以用
Outlet实现嵌套路由的批量保护:// App.js <Routes> <Route path="/" element={<Account />} /> <Route path="/free" element={<FreeComponent />} /> {/* 批量保护/auth下的所有子路由 */} <Route element={<ProtectedRoutes />}> <Route path="/auth" element={<AuthComponent />} /> <Route path="/auth/profile" element={<UserProfile />} /> </Route> </Routes> // ProtectedRoutes.js 调整为用Outlet export default function ProtectedRoutes() { const location = useLocation(); const token = cookies.get("TOKEN"); if (token) { return <Outlet />; } else { return <Navigate to="/" replace state={{ from: location }} />; } }
内容的提问来源于stack exchange,提问作者Rachel
相关产品推荐
相关产品推荐

