React Router DOM 入门指南:构建现代 React 应用的路由基石
前言:为什么我们需要路由?
在传统的 Web 开发中,不同的页面对应不同的 URL。用户点击链接时,浏览器会向服务器发送请求,服务器返回一个新的 HTML 页面,浏览器加载并显示新页面,这个过程叫做“页面跳转”或“页面刷新”。
然而,随着前端技术的发展,单页应用(Single Page Application, SPA)越来越流行。SPA 的核心思想是在页面加载后,通过 JavaScript 动态地更新页面内容,而不是每次都重新加载整个页面。这样可以带来更流畅的用户体验、更快的响应速度以及更好的用户粘性。
但是,SPA 带来了新的挑战:如何在不进行页面刷新的情况下,仍然能够根据不同的 URL 显示不同的内容?如何在不同的页面状态之间进行导航?用户如何能够通过 URL 分享当前视图或收藏特定页面?
这就是前端路由的用武之地。前端路由负责管理 URL 与 SPA 中视图之间的映射关系。当 URL 发生变化时(无论是用户手动修改、点击了内部链接还是使用了浏览器的前进/后退按钮),前端路由会拦截这个变化,并根据 URL 匹配相应的组件或内容进行渲染,而不会触发浏览器的整页刷新。
在 React 生态中,react-router-dom
是事实上的标准库,它提供了一套声明式的、灵活的 API 来构建强大的前端路由。本篇文章将带你深入了解 react-router-dom
的基本概念、核心组件及其常用用法,帮助你快速上手并构建出具备导航功能的现代 React 应用。
React Router DOM 是什么?
react-router-dom
是 react-router
库针对 Web 环境的特定绑定。react-router
提供了核心路由功能,而 react-router-dom
则在此基础上增加了在浏览器环境中运行所需的功能,例如处理 URL 历史记录 (window.history
) 和与 DOM 交互的组件(如 Link
)。
简而言之,如果你在开发基于 React 的 Web 应用,你应该安装并使用 react-router-dom
。
环境准备与安装
在开始之前,请确保你已经安装了 Node.js 和 npm 或 Yarn,并且已经创建了一个 React 项目(例如使用 Create React App 或 Vite)。
安装 react-router-dom
非常简单,只需要运行以下命令:
使用 npm:
bash
npm install react-router-dom
使用 Yarn:
bash
yarn add react-router-dom
安装完成后,你就可以在项目中引入并使用 react-router-dom
提供的组件和钩子了。
核心概念与组件
react-router-dom
的核心在于它提供了一系列 React 组件,你可以像使用其他 React 组件一样,将它们声明式地放入你的应用结构中来定义路由。以下是一些最基础和重要的组件:
-
BrowserRouter
(或HashRouter
): 这是路由器的主体,它为整个应用提供了路由上下文。通常,你需要将你的整个 React 应用包裹在其中。BrowserRouter
使用 HTML5 History API (pushState
,replaceState
等) 来保持 UI 与 URL 的同步。它创建的 URL 看起来是正常的路径(如your-app.com/about
),这是现代 Web 应用中最常用的方式。HashRouter
使用 URL 的哈希部分(如your-app.com/#/about
)来同步 UI。它不需要服务器端做特殊配置,但 URL 看起来不够美观,且不利于 SEO。- 对于大多数现代应用,推荐使用
BrowserRouter
。
-
Routes
: 在react-router-dom
v6 版本中引入,取代了之前的Switch
组件。Routes
组件的作用是遍历其所有的Route
子元素,并渲染第一个与当前 URL 匹配的Route
。这解决了之前版本中可能出现的多个Route
同时匹配的问题。 -
Route
: 这是定义路由规则的核心组件。它根据path
属性与当前 URL 进行匹配,如果匹配成功,则渲染element
属性指定的 React 元素。path
: 指定要匹配的 URL 路径。可以使用动态参数(如/users/:userId
)或星号(*
)来匹配任意路径。element
: 指定当path
匹配成功时要渲染的 React 元素(JSX)。
-
Link
: 这是用于在应用内部进行导航的组件。它渲染为一个<a>
标签,但会阻止默认的浏览器导航行为(即整页刷新),而是由react-router-dom
来处理路由转换。to
: 指定要导航的目标路径。
-
NavLink
: 这是一个特殊版本的Link
。除了导航功能外,它还能根据当前 URL 是否匹配其to
属性来自动添加一个活动的类名(默认为active
)或应用一个样式,非常适合用于制作导航菜单。
基本使用:构建一个简单的导航应用
让我们从一个最简单的例子开始,创建一个包含首页、关于页面和联系页面的应用,并实现它们之间的导航。
1. 准备组件:
首先,创建三个简单的组件,代表不同的页面:
“`jsx
// src/pages/Home.jsx
import React from ‘react’;
function Home() {
return
首页内容
;
}
export default Home;
“`
“`jsx
// src/pages/About.jsx
import React from ‘react’;
function About() {
return
关于我们
;
}
export default About;
“`
“`jsx
// src/pages/Contact.jsx
import React from ‘react’;
function Contact() {
return
联系方式
;
}
export default Contact;
“`
2. 配置路由:
接下来,修改你的主应用组件(通常是 src/App.js
或 src/App.jsx
),配置路由器和路由规则。
“`jsx
// src/App.jsx 或 src/App.js
import React from ‘react’;
import { BrowserRouter, Routes, Route, Link } from ‘react-router-dom’;
import Home from ‘./pages/Home’;
import About from ‘./pages/About’;
import Contact from ‘./pages/Contact’;
function App() {
return (
<hr />
{/* 路由配置 */}
<Routes>
{/* Route 的 path 属性定义了匹配的 URL 路径 */}
{/* element 属性定义了匹配成功时渲染的组件 */}
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
“`
3. 运行应用:
确保你的 React 项目正在运行(例如使用 npm start
或 yarn dev
)。访问你的应用地址(通常是 http://localhost:3000
或 http://localhost:5173
)。
你会看到一个带有导航链接的页面。点击“首页”、“关于”、“联系”链接,页面的内容会在下方区域切换,但整个页面不会刷新,浏览器的 URL 会随之改变。
代码解释:
BrowserRouter
包裹了整个应用,提供了路由上下文。nav
元素内部使用了Link
组件。Link
的to
属性指定了点击后要跳转的路径。它会在页面上渲染成标准的<a>
标签,但其点击行为被react-router-dom
拦截并处理。Routes
组件包裹了所有的Route
定义。它确保只有一个与当前 URL 匹配的Route
会被渲染。Route
组件通过path
属性定义了路由规则,通过element
属性指定了匹配成功时渲染的 JSX 元素(即我们的页面组件)。注意element
接收的是一个 JSX 元素 (<Home />
),而不是组件本身 (Home
)。
使用 NavLink 突出显示当前页面
在上面的例子中,导航链接没有区分当前活跃的页面。NavLink
组件就是为此设计的。它可以根据当前 URL 是否匹配其 to
属性,自动添加一个类名或应用样式。
修改导航部分的代码,将 Link
替换为 NavLink
:
“`jsx
// src/App.jsx 或 src/App.js
import React from ‘react’;
import { BrowserRouter, Routes, Route, NavLink } from ‘react-router-dom’; // 导入 NavLink
import Home from ‘./pages/Home’;
import About from ‘./pages/About’;
import Contact from ‘./pages/Contact’;
import ‘./App.css’; // 可能需要一个 CSS 文件来定义 .active 类
function App() {
// 定义一个函数来根据 isActive 状态返回类名
const navLinkClass = ({ isActive }) => {
return isActive ? ‘nav-link active’ : ‘nav-link’;
};
// 或者直接在 className 里判断
const navLinkClassName = ({ isActive }) => isActive ? ‘active’ : ”;
return (
<hr />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
“`
现在,你可以添加一些 CSS 规则来美化 .active
类:
“`css
/ src/App.css /
.nav-link {
margin-right: 15px;
text-decoration: none;
color: #333;
}
.nav-link.active {
font-weight: bold;
color: blue; / 活跃链接显示为蓝色 /
text-decoration: underline;
}
“`
当你点击不同的导航链接时,当前页面的链接会被赋予 .active
类,从而应用相应的样式。
NavLink 的 end
属性:
默认情况下,NavLink
会进行“部分匹配”。例如,如果当前 URL 是 /about/team
,path="/about"
的 NavLink
也会被视为活跃。在上面的例子中,如果首页 /
的 NavLink
没有特别处理,它可能会在访问 /about
或 /contact
时也被标记为活跃(因为 /
路径是所有路径的前缀)。
为了解决这个问题,你可以给首页的 NavLink
加上 end
属性:
jsx
<NavLink to="/" className={navLinkClassName} end>
首页
</NavLink>
end
属性表示只有当 URL 完全匹配到 to
属性指定的路径时,这个 NavLink
才会被视为活跃。对于 /
路径,这尤其重要,因为它是所有路径的开始。对于 /about
或 /contact
等更具体的路径,通常不需要 end
。
动态路由:处理 URL 参数
很多时候,我们需要在 URL 中包含一些动态信息,例如用户的 ID、产品的 SKU 等。这些信息需要在渲染组件时能够获取到。react-router-dom
支持在 Route
的 path
中定义 URL 参数。
1. 定义带有参数的 Route:
在 path
中使用冒号 :
前缀来定义参数名。例如 /users/:userId
表示 /users/
后面的部分是一个叫做 userId
的参数。
jsx
<Route path="/users/:userId" element={<UserProfile />} />
2. 在组件中获取参数:
使用 useParams
钩子来获取当前匹配到的 URL 参数对象。
首先,创建一个 UserProfile
组件:
“`jsx
// src/pages/UserProfile.jsx
import React from ‘react’;
import { useParams } from ‘react-router-dom’;
function UserProfile() {
// useParams 钩子返回一个对象,其属性名对应 Route path 中定义的参数名
const { userId } = useParams();
return (
用户详情页面
当前用户 ID 是: {userId}
{/ 根据 userId 从 API 获取用户数据并显示 /}
);
}
export default UserProfile;
“`
3. 在应用中配置和使用:
在 App.jsx
或 App.js
中添加这个新的 Route:
“`jsx
// src/App.jsx 或 src/App.js
import React from ‘react’;
import { BrowserRouter, Routes, Route, NavLink } from ‘react-router-dom’;
import Home from ‘./pages/Home’;
import About from ‘./pages/About’;
import Contact from ‘./pages/Contact’;
import UserProfile from ‘./pages/UserProfile’; // 导入 UserProfile
// … NavLink className helper …
function App() {
return (
<hr />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
{/* 添加动态路由 */}
<Route path="/users/:userId" element={<UserProfile />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
“`
现在,当你访问 /users/123
或 /users/abc
等 URL 时,UserProfile
组件会被渲染,并通过 useParams
获取到对应的 userId
值。
嵌套路由:构建复杂布局
在实际应用中,页面的结构往往是分层的。例如,一个仪表盘页面可能包含用户列表、设置、统计等子页面,并且这些子页面共享仪表盘的侧边栏或顶部导航。这就是嵌套路由的常见场景。
react-router-dom
v6 中,嵌套路由的实现方式更加直观:在父级 Route
中定义子级 Route
,并在父级组件中使用 Outlet
组件来指示子路由的渲染位置。
1. 创建父级布局组件:
这个组件将包含共享的布局元素(如侧边栏、子导航)以及一个 Outlet
,Outlet
是子路由渲染的地方。
“`jsx
// src/pages/DashboardLayout.jsx
import React from ‘react’;
import { Outlet, Link } from ‘react-router-dom’;
function DashboardLayout() {
return (
仪表盘
{/ 仪表盘子导航 /}
<hr />
{/* Outlet 是子路由渲染的位置 */}
<div style={{ border: '1px solid #ccc', padding: '10px' }}>
<h3>子页面内容区域:</h3>
<Outlet />
</div>
</div>
);
}
export default DashboardLayout;
``
*注意:* 在中,可以使用相对路径 (
to=”overview”,
to=”settings”),但使用绝对路径 (
to=”/dashboard/overview”) 可以避免一些歧义,特别是当你从不同的父级路由进入嵌套路由时。在
v6中,相对路径是默认行为,且通常推荐。例如,在
/dashboard页面,
to=”overview”会导航到
/dashboard/overview。如果你在
/页面,
to=”dashboard/overview”也会导航到
/dashboard/overview`。理解相对路径的行为对于嵌套路由很重要。让我们修改 Link 为相对路径示例:
“`jsx
// src/pages/DashboardLayout.jsx (使用相对路径 Link 示例)
import React from ‘react’;
import { Outlet, Link } from ‘react-router-dom’;
function DashboardLayout() {
return (
仪表盘
<hr />
<div style={{ border: '1px solid #ccc', padding: '10px' }}>
<h3>子页面内容区域:</h3>
<Outlet />
</div>
</div>
);
}
export default DashboardLayout;
“`
2. 创建子级页面组件:
“`jsx
// src/pages/DashboardOverview.jsx
import React from ‘react’;
function DashboardOverview() {
return
总览内容
;
}
export default DashboardOverview;
“`
“`jsx
// src/pages/DashboardSettings.jsx
import React from ‘react’;
function DashboardSettings() {
return
设置内容
;
}
export default DashboardSettings;
“`
3. 配置嵌套路由:
在 App.jsx
或 App.js
中,将子 Route
定义在父 Route
的内部。父 Route
定义了共享的路径前缀和布局组件。
“`jsx
// src/App.jsx 或 src/App.js
import React from ‘react’;
import { BrowserRouter, Routes, Route, NavLink } from ‘react-router-dom’;
import Home from ‘./pages/Home’;
import About from ‘./pages/About’;
import Contact from ‘./pages/Contact’;
import UserProfile from ‘./pages/UserProfile’;
import DashboardLayout from ‘./pages/DashboardLayout’; // 导入布局组件
import DashboardOverview from ‘./pages/DashboardOverview’; // 导入子组件
import DashboardSettings from ‘./pages/DashboardSettings’; // 导入子组件
// … NavLink className helper …
function App() {
return (
<hr />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
<Route path="/users/:userId" element={<UserProfile />} />
{/* 配置嵌套路由 */}
{/* 父级 Route 定义了前缀 /dashboard 和布局组件 DashboardLayout */}
<Route path="/dashboard" element={<DashboardLayout />}>
{/* 子级 Route 定义了相对于父级路径的后缀和对应的组件 */}
{/* path="overview" 表示匹配 /dashboard/overview */}
<Route path="overview" element={<DashboardOverview />} />
{/* path="settings" 表示匹配 /dashboard/settings */}
<Route path="settings" element={<DashboardSettings />} />
{/* 你还可以定义一个 index 路由作为父级路径的默认内容 */}
{/* path="/" 或 index=true 都表示匹配父级路径 (/dashboard) */}
<Route index element={<DashboardOverview />} />
{/* 或者使用 path="" */}
{/* <Route path="" element={<DashboardOverview />} /> */}
</Route>
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
“`
现在,当你访问 /dashboard
时,会渲染 DashboardLayout
及其内部的 Outlet
位置会渲染 DashboardOverview
(因为我们设置了 index
路由)。访问 /dashboard/overview
会渲染 DashboardOverview
,访问 /dashboard/settings
会渲染 DashboardSettings
,它们都将显示在 DashboardLayout
定义的布局区域内。
Index Routes:
在嵌套路由中,index
路由 (<Route index element={<Component />} />
) 是一个非常实用的概念。它表示当父级路径完全匹配时(例如访问 /dashboard
),默认渲染哪个子组件。这避免了需要单独定义一个 /dashboard
路径来渲染默认内容。index
路由等价于 <Route path="" element={<Component />} />
,但更具语义化。
404 页面(未匹配路由)
如何处理用户访问了一个不存在的 URL?我们需要一个“页面未找到”(404)页面。在 react-router-dom
v6 中,这非常简单:在 Routes
的最后添加一个使用星号 *
作为 path
的 Route
。星号 *
表示匹配任何路径。由于 Routes
会渲染第一个匹配的 Route
,将 path="*"
放在最后可以确保只有在所有其他更具体的路由都未匹配时,它才会被渲染。
1. 创建 404 组件:
“`jsx
// src/pages/NotFound.jsx
import React from ‘react’;
function NotFound() {
return (
404 – 页面未找到
抱歉,你访问的页面不存在。
);
}
export default NotFound;
“`
2. 在 Routes 最后添加 Route:
“`jsx
// src/App.jsx 或 src/App.js
import React from ‘react’;
import { BrowserRouter, Routes, Route, NavLink } from ‘react-router-dom’;
// … 其他导入 …
import NotFound from ‘./pages/NotFound’; // 导入 NotFound 组件
// … App component …
function App() {
return (
<hr />
<Routes>
{/* ... 其他 Route ... */}
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
<Route path="/users/:userId" element={<UserProfile />} />
{/* 嵌套路由示例 */}
<Route path="/dashboard" element={<DashboardLayout />}>
<Route path="overview" element={<DashboardOverview />} />
<Route path="settings" element={<DashboardSettings />} />
<Route index element={<DashboardOverview />} />
</Route>
{/* 404 路由:放在所有其他路由之后 */}
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
“`
现在,当你访问任何未匹配上述路径的 URL 时(例如 /non-existent-page
),你将会看到“404 – 页面未找到”的内容。
程序化导航:useNavigate 钩子
除了点击 Link
或 NavLink
进行导航外,有时我们需要在代码中触发导航,例如:
- 用户成功登录后跳转到仪表盘。
- 用户提交表单后跳转到详情页。
- 点击一个按钮来返回上一页。
react-router-dom
提供了 useNavigate
钩子来实现程序化导航。
1. 在组件中使用 useNavigate
:
“`jsx
// src/pages/DashboardOverview.jsx (示例,添加一个按钮用于导航)
import React from ‘react’;
import { useNavigate } from ‘react-router-dom’;
function DashboardOverview() {
const navigate = useNavigate();
const handleGoToSettings = () => {
// 使用 navigate 函数进行导航
// navigate(‘/dashboard/settings’); // 绝对路径
navigate(‘settings’); // 相对路径 (推荐在嵌套路由中使用相对路径)
};
const handleGoHome = () => {
navigate(‘/’); // 导航回首页
};
const handleGoBack = () => {
navigate(-1); // 导航回上一页 (相当于点击浏览器后退按钮)
};
const handleReplaceHistory = () => {
// 导航并替换当前历史记录,用户无法通过后退按钮返回当前页
navigate(‘/contact’, { replace: true });
};
const handleNavigateWithState = () => {
// 导航并传递 state 数据,可以在目标页面通过 useLocation 获取
navigate('/about', { state: { from: 'dashboard', data: 123 } });
};
return (
总览内容
欢迎来到仪表盘!
);
}
export default DashboardOverview;
“`
navigate
函数的用法:
navigate(to)
: 导航到指定的路径to
。to
可以是字符串(绝对路径或相对路径),也可以是一个数字(例如navigate(-1)
表示后退一页,navigate(1)
表示前进一页)。navigate(to, { replace: true })
: 导航到指定路径,但不是将新路径添加到历史记录中,而是替换掉当前的历史记录。常用于登录成功后,不希望用户通过后退回到登录页。navigate(to, { state: data })
: 导航到指定路径,并附带一些 state 数据。这些数据可以在目标页面通过useLocation
钩子获取。
其他常用钩子
除了 useParams
和 useNavigate
,react-router-dom
还提供了其他一些有用的钩子:
-
useLocation
: 返回一个location
对象,表示当前 URL 的信息,包括pathname
(路径名),search
(查询字符串,如?key=value
),hash
(URL 哈希), 和state
(通过navigate
传递的状态)。
“`jsx
import { useLocation } from ‘react-router-dom’;function CurrentPageInfo() {
const location = useLocation();console.log(location.pathname); // ‘/about’
console.log(location.search); // ‘?query=test’
console.log(location.hash); // ‘#section’
console.log(location.state); // { from: ‘dashboard’, data: 123 } (如果navigate时传递了state)// 解析查询参数
const queryParams = new URLSearchParams(location.search);
console.log(queryParams.get(‘query’)); // ‘test’return (
当前路径: {location.pathname}
查询参数: {location.search}
哈希: {location.hash}
{location.state &&
State 数据: {JSON.stringify(location.state)}
}
);
}
* **`useMatch`**: 检查当前 `location` 是否与给定的路径模式匹配。它返回一个匹配对象(如果匹配成功)或 `null`(如果匹配失败)。这对于需要在渲染时判断当前路径是否与某个模式匹配的情况很有用。
jsx
import { useMatch } from ‘react-router-dom’;function ConditionalComponent() {
// 检查当前路径是否匹配 /users/:userId
const match = useMatch(‘/users/:userId’);if (match) {
// match.params 包含提取的参数
console.log(“匹配的用户 ID:”, match.params.userId);
return当前正在查看用户 ID 为 {match.params.userId} 的详情。
;
}return
当前不在用户详情页。
;
}
“`
高级概念(简述)
-
Layout Routes: 在嵌套路由中,父级
Route
不指定path
属性,只提供element
属性,并在其内部定义子Route
。这种方式可以方便地将通用布局应用于一组子路由,而不需要父级路径前缀。
jsx
<Routes>
{/* 这是一个布局路由 */}
<Route element={<AppLayout />}>
{/* 这些子路由将使用 AppLayout */}
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Route>
</Routes>
这里的<AppLayout>
组件内部需要包含<Outlet />
来渲染匹配到的子路由组件。 -
身份验证与路由保护: 实际应用中,很多页面需要用户登录后才能访问。你可以创建一个高阶组件或一个自定义路由组件来检查用户登录状态,如果未登录,则重定向到登录页。结合
useNavigate
或Navigate
组件可以实现路由保护。
“`jsx
import { Navigate, Outlet } from ‘react-router-dom’;
import { useAuth } from ‘./authContext’; // 假设你有一个认证上下文function ProtectedRoute() {
const auth = useAuth(); // 获取认证状态// 如果未登录,重定向到登录页
if (!auth.user) {
return;
}// 如果已登录,渲染子路由内容
return;
}// 在你的 Routes 中使用
} />
{/ 使用 ProtectedRoute 包裹需要保护的路由 /}
}>
} />
} />
{/ … 其他需要保护的路由 … /}
{/ … 其他公共路由 … /}
“` -
Code Splitting (代码分割): 对于大型应用,一次性加载所有路由对应的组件可能会导致初始加载时间过长。
react-router-dom
可以与React.lazy
和Suspense
结合使用,实现路由级别的代码分割,按需加载组件。
“`jsx
import React, { Suspense } from ‘react’;
import { BrowserRouter, Routes, Route } from ‘react-router-dom’;// 使用 React.lazy 动态导入组件
const Home = React.lazy(() => import(‘./pages/Home’));
const About = React.lazy(() => import(‘./pages/About’));function App() {
return (
{/ Suspense 提供加载时的 fallback /}
Loading…\
}>
);
}
“`
总结
react-router-dom
是构建现代 React 单页应用导航功能的强大而灵活的库。通过本指南,你应该已经掌握了以下核心概念和用法:
BrowserRouter
: 包裹应用以提供路由上下文。Routes
: 组织和匹配Route
定义。Route
: 将path
映射到要渲染的element
。Link
: 声明式导航到应用内的不同路径,避免整页刷新。NavLink
: 增强的Link
,可以高亮显示活跃链接。useParams
: 在组件中获取 URL 动态参数。useNavigate
: 程序化地进行页面跳转。Outlet
: 在父级路由组件中指定子路由的渲染位置。- 嵌套路由: 使用
<Route>
嵌套定义复杂页面结构。 - 404 路由: 使用
path="*"
捕获未匹配的路径。 useLocation
: 获取当前 URL 的详细信息。
通过这些组件和钩子,你可以轻松地为你的 React 应用添加导航功能,实现多视图切换和复杂的路由逻辑。记住,最好的学习方式是动手实践。尝试在你的项目中应用这些知识,并参考官方文档(https://reactrouter.com/)获取更深入的信息和最新的 API 用法。
祝你在 React 路由的学习旅程中顺利!