React Router 极简指南(v6+)

这是一篇为你梳理的 React Router 核心知识文章,精简、到位、易懂,帮助你快速掌握 React 路由的用法。


前言

React Router 是 React 应用中最流行的路由库,它允许你在单页应用中实现多页面导航,保持 UI 与 URL 同步。当前主流版本是 v6,如果你还在用 v5,建议升级------v6 的 API 更简洁,思维模型也更清晰。

一、核心思想

一句话:根据 URL 的不同,渲染不同的组件。

React Router 将"路由"看作一个组件树,URL 变化时,它会匹配对应的 <Route>,然后把组件渲染到 <Outlet> 位置。

二、三个必须知道的组件

1. BrowserRouter

包裹整个应用,提供路由上下文。通常放在最外层:

jsx 复制代码
import { BrowserRouter } from 'react-router-dom';

root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

2. RoutesRoute

Routes 是 v6 新增的容器,替代了 v5 的 SwitchRoute 定义路径与组件的映射。

jsx 复制代码
import { Routes, Route } from 'react-router-dom';

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
    </Routes>
  );
}

要点:

  • 使用 element 属性(不再是 component)。
  • 匹配规则变为"最佳匹配",不再需要 exact

声明式导航,替代 <a> 标签,避免整页刷新。

jsx 复制代码
import { Link, NavLink } from 'react-router-dom';

<Link to="/about">关于</Link>

// NavLink 可以知道当前是否激活,用于菜单高亮
<NavLink to="/about" className={({ isActive }) => isActive ? 'active' : ''}>
  关于
</NavLink>

三、嵌套路由与布局

v6 的嵌套路由不需要再写一大堆 /*,直接嵌套 <Route> 即可。父组件使用 <Outlet /> 来渲染子路由。

jsx 复制代码
// 定义路由
<Routes>
  <Route path="/dashboard" element={<Dashboard />}>
    <Route path="stats" element={<Stats />} />
    <Route path="settings" element={<Settings />} />
  </Route>
</Routes>

// Dashboard 组件
function Dashboard() {
  return (
    <div>
      <h1>控制台</h1>
      <nav>...</nav>
      <Outlet /> {/* 子路由的内容会显示在这里 */}
    </div>
  );
}

访问 /dashboard/stats 时,DashboardStats 会一起渲染,完美实现布局复用。

四、动态路由与参数

用冒号 :id 定义动态段,在组件中通过 useParams 读取。

jsx 复制代码
<Route path="/users/:userId" element={<UserProfile />} />

// UserProfile 组件内
import { useParams } from 'react-router-dom';

function UserProfile() {
  const { userId } = useParams();
  // 根据 userId 请求数据...
}

五、编程式导航

不能用 <Link> 的场景(例如按钮点击后跳转),使用 useNavigate

jsx 复制代码
import { useNavigate } from 'react-router-dom';

function LoginButton() {
  const navigate = useNavigate();
  const handleLogin = async () => {
    await loginApi();
    navigate('/dashboard'); // 普通跳转
    // navigate(-1); // 返回上一页
  };
  return <button onClick={handleLogin}>登录</button>;
}

六、查询参数(Query String)

v6 没有内置的 useQuery,推荐用浏览器原生的 URLSearchParams 来处理。

jsx 复制代码
import { useSearchParams } from 'react-router-dom';

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

  const updateKeyword = (newKeyword) => {
    setSearchParams({ q: newKeyword });
  };
  // ...
}

useSearchParams 的用法和 useState 类似,读写查询参数非常方便。

七、404 页面与索引路由

jsx 复制代码
<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/dashboard" element={<Dashboard />}>
    <Route index element={<DashboardHome />} /> {/* 访问 /dashboard 时显示 */}
    <Route path="stats" element={<Stats />} />
  </Route>
  <Route path="*" element={<NotFound />} /> {/* 必须放在最后 */}
</Routes>
  • index 路由:父路径精确匹配时渲染的默认子组件。
  • * 通配路由:捕获所有未匹配的路径,常用于 404 页面。

八、保护路由(权限控制)

可以封装一个 ProtectedRoute 组件,根据登录状态决定是渲染子组件还是重定向。

jsx 复制代码
function ProtectedRoute({ children }) {
  const isAuthenticated = useAuth(); // 自定义 Hook,返回用户登录状态
  const location = useLocation();

  if (!isAuthenticated) {
    // 把当前路径传给登录页,登录后可跳回
    return <Navigate to="/login" state={{ from: location }} replace />;
  }
  return children;
}

// 用法
<Route path="/dashboard" element={
  <ProtectedRoute>
    <Dashboard />
  </ProtectedRoute>
} />

九、v6 变化一览(对比 v5)

v5 v6
<Switch> <Routes>
component={Comp} element={<Comp />}
无序匹配 + exact 自动最佳匹配
嵌套需写完整路径或 useRouteMatch 直接相对路径嵌套 + <Outlet>
useHistory useNavigate
useRouteMatch 无,用相对路径和 useParams 等替代
类组件支持 全面拥抱 Hooks

十、最佳实践速记

  1. 路由集中定义:将所有路由放在一个配置文件中,清晰可维护。
  2. 懒加载组件 :结合 React.lazy()Suspense 实现代码分割。
  3. 始终考虑 404 :加一条 path="*" 的路由。
  4. 导航高亮用 NavLink:比手动判断更简洁。
  5. 权限等逻辑抽象成 wrapper 组件:保持路由配置干净。

总结

React Router 的核心就这么简单。掌握以上内容,你就能应对 90% 的实际项目需求。当需要更高级特性(如数据加载、路由过渡动画)时,再去查阅官方文档,你会发现自己已经有扎实的底子去理解它们了。

相关推荐
Maimai108089 分钟前
React如何用 @microsoft/fetch-event-source 落地 SSE:比原生 EventSource 更灵活的实时推送方案
前端·javascript·react.js·microsoft·前端框架·reactjs·webassembly
kyriewen2 小时前
产品经理把PRD写成“天书”,我用AI半小时重写了一遍,他当场愣住
前端·ai编程·cursor
humcomm2 小时前
元框架的工作原理详解
前端·前端框架
canonical_entropy2 小时前
Attractor Before Harness: AI 大规模开发的方法论
前端·aigc·ai编程
zhangxingchao3 小时前
多 Agent 架构到底怎么选?从 Claude Agent Teams、Cognition/Devin 到工程落地原则
前端·人工智能·后端
IT_陈寒3 小时前
SpringBoot那个自动配置的坑,害我排查到凌晨三点
前端·人工智能·后端
Honor丶Onlyou3 小时前
VS Code 右键菜单修复记录
前端
PILIPALAPENG3 小时前
Python 语法速成指南:前端开发者视角(JS 类比版)
前端·人工智能·python
JYeontu3 小时前
轮播图不够惊艳?试下这个立体卡片轮播图
前端·javascript·css
张就是我1065923 小时前
从前端角度理解 CVE-2026-31431
前端