阅读视图

发现新文章,点击刷新页面。

Ract Router v7:最全基础与高级用法指南(可直接上手)

React Router v7 已经正式成为现代 React 应用的默认路由方案。相比过去的版本,v7 在数据加载、路由懒加载、错误边界、路由模块化等方面做了更统一、更现代化的设计。

本文带你快速掌握 基础用法 + 高级用法,适合从 v5/v6 升级或新项目使用

一、核心理念与变化概览

React Router v7 主要围绕三个关键词:

1. 路由是 UI 的一部分

-router 是组件

  • 不再是配置式为主,组件式更自然
  • Layout + Outlet 成为主流

2. 数据路由(Data Router)统一化

提供统一 API:

  • loader 数据加载
  • action 数据提交
  • lazy 懒加载路由资源
  • errorElement 错误边界

3. 组件即路由

v7 保留了 v6 的 createBrowserRouterRouterProvider,并继续强化嵌套路由的概念

二、基础用法

1. 安装

npm install react-router-dom

2. 最简路由结构

import { createBrowserRouter, RouterProvider } from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/",
    element: <HomePage />,
  },
  {
    path: "/about",
    element: <AboutPage />,
  },
]);

export default function App() {
  return <RouterProvider router={router} />;
}

3. Layout + Outlet(嵌套路由)

Layout 是 v7 强调的最佳实践:

import { Outlet, Link } from "react-router-dom";

function Layout() {
  return (
    <div>
      <nav>
        <Link to="/">首页</Link>
        <Link to="/profile">个人中心</Link>
      </nav>

      <main>
        <Outlet /> {/* 子路由在这里渲染 */}
      </main>
    </div>
  );
}

const router = createBrowserRouter([
  {
    path: "/",
    element: <Layout />,
    children: [
      { index: true, element: <HomePage /> },
      { path: "profile", element: <ProfilePage /> },
    ],
  },
]);

三、懒加载(async lazy)——强烈推荐写法

React Router v7 官方推荐使用 async lazy() 来进行路由级按需加载。

🔥 推荐写法:async lazy()

const router = createBrowserRouter([
  {
    path: "/",
    async lazy() {
      const Component = (await import("./pages/Layout")).default;
      return { Component };
    },
    children: [
      {
        index: true,
        async lazy() {
          const Component = (await import("./pages/Home")).default;
          return { Component };
        },
      },
      {
        path: "profile",
        async lazy() {
          const Component = (await import("./pages/Profile")).default;
          return { Component };
        },
      },
    ],
  },
]);

优势:
✔ 语法干净
✔ 和 Data Router 完整兼容
✔ 自动 Suspense
✔ 支持 SSR(未来版本)
✔ 大型项目结构清晰

四、跳转与参数读取

1. 跳转

const navigate = useNavigate();
navigate("/profile");

2. 获取路径参数

const { id } = useParams();

3. 获取查询参数

const [searchParams] = useSearchParams();
const keyword = searchParams.get("keyword");

五、跳转与参数读取(加强版)

这一部分很多人用得不全,这里讲 跳转方式、路径参数、查询参数、状态传参 4 大类。


📌 1. 跳转导航

(1)useNavigate:最常用跳转

import { useNavigate } from "react-router-dom";

const nav = useNavigate();

nav("/profile");                 // 普通跳转
nav(-1);                         // 返回上一页
nav("/login", { replace: true }); // 不留历史记录

(2)链接跳转 Link

import { Link } from "react-router-dom";

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

(3)按钮跳转 Navigate 组件

适合条件跳转:

{ isLogin ? <Dashboard /> : <Navigate to="/login" replace /> }

📌 2. 路径参数(URL Params)

例如访问:
/user/123

定义路由:

{
  path: "user/:id",
  element: <UserDetail />
}

读取参数:

import { useParams } from "react-router-dom";

const { id } = useParams(); // id === "123"

注意:

  • params 一定是字符串类型
  • 可用 Zod/Number() 做转换

📌 3. 查询参数(Search Params)

例如访问:
/list?page=2&keyword=test

读取:

import { useSearchParams } from "react-router-dom";

const [search] = useSearchParams();

const page = search.get("page"); 
const keyword = search.get("keyword");

修改:

const [search, setSearch] = useSearchParams();

setSearch({ page: 3 });

支持 append:

search.append("type", "A");
setSearch(search);

📌 4. 跳转时携带 state(非 URL)

类似 history.push 的 state:

nav("/detail", {
  state: { from: "list", id: 123 }
});

读取:

import { useLocation } from "react-router-dom";

const { state } = useLocation();
// state.from === "list"

用法:

  • 搜索列表 → 详情
  • 跨页面临时数据
  • 不污染 URL
  • 仅会话内有效

六、Data Router:loader 与 action(高级)

📌 为什么需要 Data Router?

传统 SPA 数据加载流程:

渲染组件 → useEffect → fetch 数据 → setState →再渲染

但这有几个问题:

  • 多层嵌套时 useEffect 非常乱
  • SSR、预加载、切换页面时不能保证一致性
  • 异步错误很难集中处理
  • 首屏渲染过慢
  • React 渲染后才请求数据,白屏时间更长

React Router v7 引入 Data Router 后,流程变成:

进入某个路由 → 执行 loader → 数据准备好 → 再渲染组件

好处:

  • 页面渲染 之前 就拿到数据(首屏更快)
  • 数据逻辑从 UI 分离
  • 错误自动走路由 errorElement
  • 多个 loader 并行执行
  • 支持自动 revalidate(自动刷新)
  • SSR & CSR 统一开发体验

📌 1. loader:加载页面数据

loader 是路由级数据加载函数:

{
  path: "/detail/:id",
  loader: async ({ params, request }) => {
    const res = await fetch(`/api/detail/${params.id}`);
    return res.json();
  },
  element: <DetailPage />
}

组件内读取:

import { useLoaderData } from "react-router-dom";

const data = useLoaderData();

2. action:表单提交逻辑

{
  path: "/create",
  action: async ({ request }) => {
    const form = await request.formData();
    return createItem(form);
  },
  element: <CreatePage />
}

配合 <Form>

<Form method="post">
  <input name="title" />
  <button>提交</button>
</Form>

七、错误边界 errorElement

v7 支持路由级错误 UI:

{
  path: "/",
  element: <Layout />,
  errorElement: <ErrorPage />,
}

读取异常:

const err = useRouteError();

八、handle:路由元信息(meta)

可用于:

  • 页面标题
  • 面包屑
  • 权限
  • 路由描述
{
  path: "settings",
  handle: { title: "系统设置", auth: true },
  element: <SettingsPage />
}

读取所有匹配路由的 handle:

import { useMatches } from "react-router-dom";

const matches = useMatches();

九、模块化路由(大型项目最佳实践)

假设有三个模块:Dashboard、User、Project

1️⃣ Dashboard 模块

// routes/dashboard.routes.ts
export const dashboardRoutes = [
  {
    path: "dashboard",
    async lazy() {
      const Component = (await import("@/pages/Dashboard")).default;
      return { Component };
    },
    handle: { title: "Dashboard" },
  },
];

2️⃣ User 模块(带 loader/action)

// routes/user.routes.ts
export const userRoutes = [
  {
    path: "user",
    async lazy() {
      const Layout = (await import("@/pages/User/Layout")).default;
      return { Component: Layout };
    },
    children: [
      {
        index: true,
        async lazy() {
          const Component = (await import("@/pages/User/List")).default;
          return { Component };
        },
        handle: { title: "用户列表" },
      },
    ],
  },
];

3️⃣ Project 模块

// routes/project.routes.ts
export const projectRoutes = [
  {
    path: "project",
    async lazy() {
      const Layout = (await import("@/pages/Project/Layout")).default;
      return { Component: Layout };
    },
    children: [
      {
        index: true,
        async lazy() {
          const Component = (await import("@/pages/Project/List")).default;
          return { Component };
        },
        handle: { title: "项目列表" },
      },
     
    ],
  },
];

4️⃣ 主路由统一整合

// routes/index.ts
import { createBrowserRouter } from "react-router-dom";
import { dashboardRoutes } from "./dashboard.routes";
import { userRoutes } from "./user.routes";
import { projectRoutes } from "./project.routes";

const router = createBrowserRouter([
  {
    path: "/",
    async lazy() {
      const Layout = (await import("@/pages/Layout")).default;
      return { Component: Layout };
    },
    children: [
      ...dashboardRoutes,
      ...userRoutes,
      ...projectRoutes,
    ],
  },
  {
    path: "/login",
    async lazy() {
      const Component = (await import("@/pages/Login")).default;
      return { Component };
    },
  },
  {
    path: "*",
    async lazy() {
      const Component = (await import("@/pages/NotFound")).default;
      return { Component };
    },
  },
]);

export default router;

十、权限控制(结合 loader + handle)

{
  path: "admin",
  handle: { auth: true },
  loader: async () => {
    const login = await checkLogin();
    if (!login) throw redirect("/login");
  },
  element: <Admin />
}

满足所有权限场景。


结语

React Router v7 是目前 React 生态最全面的 SPA/SSR 路由方案,它的优势包括:

  • 统一的页面加载方式
  • 按需加载(lazy)
  • 模块化路由
  • 真正意义的路由数据层
  • 强大的错误边界和 handle

无论是小项目还是大型管理后台,它都足够可控且可扩展。

❌