ToolkitX
知识库工具箱

路由管理

React Router v6 详解

20min·进阶

01. React Router v6 的基本概念

React Router 是 React 事实上的路由标准。v6 相比 v5 有了重大变化——API 更简洁、路由匹配更智能、全面拥抱 React Hooks。 核心组件: BrowserRouter——包裹整个应用,提供浏览器历史记录。 Routes——路由表容器,里面是一堆 Route。 Route——定义路径和组件的映射。path 是 URL 路径,element 是渲染的组件。 Link——导航链接,点击不刷新页面。相当于 a 标签但不会重新加载。 Outlet——子路由的插槽。父路由组件里放一个 Outlet,子路由组件就渲染在那里。 useParams——在组件里读取 URL 参数(如 /user/:id 中的 id)。 useNavigate——编程式导航,跳转到指定路径。 useLocation——获取当前 URL 信息。
jsx
import { BrowserRouter, Routes, Route, Link, useParams } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/users">Users</Link>
      </nav>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/users" element={<UserList />} />
        <Route path="/users/:id" element={<UserDetail />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}

function UserDetail() {
  const { id } = useParams();
  return <div>User: {id}</div>;
}

02. 嵌套路由——Layout 布局模式

嵌套路由是 React Router v6 最强大的特性之一。你可以在父路由里定义共享的 Layout,子路由的内容通过 Outlet 渲染在 Layout 里的某个位置。 典型场景:后台管理系统——侧边栏和顶部导航是共用的,中间内容区根据路由变化。 嵌套路由的写法:父 Route 不设 path(或设为共享前缀),子 Route 直接写在父 Route 里面。子路由的 path 是相对路径,自动拼接。 Outlet 是子路由的占位符。Layout 组件里放一个 Outlet,子路由匹配到的组件就在这渲染。 useOutletContext——父路由可以通过 Outlet context prop 传数据给子路由。比 Context 更直接。
jsx
// 嵌套路由——后台管理系统布局
function AdminLayout() {
  return (
    <div className="admin">
      <Sidebar />
      <div className="content">
        <Outlet />
      </div>
    </div>
  );
}

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/admin" element={<AdminLayout />}>
        <Route index element={<Dashboard />} />
        <Route path="users" element={<Users />} />
        <Route path="users/:id" element={<UserEdit />} />
        <Route path="settings" element={<Settings />} />
      </Route>
    </Routes>
  );
}
// /admin → Dashboard
// /admin/users → Users
// /admin/users/1 → UserEdit
index 路由是父路径精确匹配时渲染的默认子路由。Route index 不加 path,只在父路径完全匹配时显示。

03. 路由守卫——权限控制

实际项目里不是所有页面都能公开访问。需要登录的页面要加路由守卫——没登录就重定向到登录页。 实现方式:写一个 ProtectedRoute 组件包裹需要保护的路由。在组件里检查是否登录(从 Context/Zustand/Redux 里拿用户状态),没登录就 Navigate 到登录页。 v6 的做法不是装饰器式的,而是用元素包裹:element={<ProtectedRoute><Dashboard /></ProtectedRoute>}。 更灵活的方案是用一个配置数组定义路由表,每个路由项加 requiresAuth 标记。统一遍历生成路由。
jsx
// 路由守卫组件
function ProtectedRoute({ children }) {
  const user = useAuthStore(s => s.user);

  if (!user) {
    return <Navigate to="/login" replace />;
  }

  return children;
}

// 使用
<Routes>
  <Route path="/login" element={<Login />} />
  <Route path="/dashboard" element={
    <ProtectedRoute>
      <Dashboard />
    </ProtectedRoute>
  } />
</Routes>

// 或者用布局路由统一保护
<Route element={<ProtectedRoute />}>
  <Route path="/dashboard" element={<Dashboard />} />
  <Route path="/settings" element={<Settings />} />
</Route>

04. 编程式导航与参数传递

useNavigate 返回一个 navigate 函数,可以编程跳转——表单提交后跳到成功页、按钮点击跳转。 跳转方式: navigate('/path')——直接跳到目标路径。 navigate(-1)——后退一页。 navigate('/path', { replace: true })——替换当前历史记录而不是新增(用户按后退不会回到当前页)。 navigate('/path', { state: { data } })——传递状态给目标页面。 接收 state——目标页面用 useLocation() 获取 location.state。但注意:直接访问 URL(不是从导航跳转来的)时 state 是 null。 URL 参数(useParams)比 state 更可靠——参数存在 URL 里,刷新后还在。state 存在浏览器的 history 里,刷新可能会丢。
jsx
function SubmitForm() {
  const navigate = useNavigate();

  const handleSubmit = async (data) => {
    await saveData(data);
    navigate('/success', { state: { message: '保存成功' } });
  };

  return <form onSubmit={...}>...</form>;
}

function SuccessPage() {
  const location = useLocation();
  const message = location.state?.message || '操作成功';

  return <div>{message}</div>;
}

// 后退
// navigate(-1);
URL 参数是持久化的(刷新还在),state 是临时的。需要刷新后还能继续的信息放 URL 参数而不是 state。

05. React Router v6 的常见问题

1. BrowserRouter vs HashRouter——BrowserRouter 需要服务器配置(所有路径返回 index.html),HashRouter 不需要但 URL 里会有 #。生产环境推荐 BrowserRouter。 2. 路由不匹配——v6 的路由匹配默认精确。/users 不会匹配 /users/123,除非你在 /users 路由下写了一个相对路由。 3. 404 页面——用 Route path="*" 兜底,匹配所有不认识的路径。 4. 相对路径 & 绝对路径——Link to="about" 是相对于当前路径,Link to="/about" 是绝对路径。嵌套路由里容易搞混。 5. useSearchParams——获取和设置 URL 的查询参数(?key=value)。像 useState 一样用。
jsx
// HashRouter 不需要服务端配置
import { HashRouter } from 'react-router-dom';

// 404 兜底
<Route path="*" element={<NotFound />} />

// useSearchParams
function SearchPage() {
  const [searchParams, setSearchParams] = useSearchParams();
  const keyword = searchParams.get('q') || '';

  return (
    <input
      value={keyword}
      onChange={e => setSearchParams({ q: e.target.value })}
    />
  );
}
BrowserRouter 需要 Nginx 配 try_files $uri /index.html。不然直接访问 /users/123 会 404。HashRouter 不需要但 URL 不够干净。

知识测验

1/5正确 0

React Router v6 的 Outlet 组件是什么?

下一节

性能优化

下一节