路由对象
本页内容

路由对象

简介

传递给 createBrowserRouter 的对象称为路由对象。

createBrowserRouter([
  {
    path: "/",
    Component: App,
  },
]);

路由模块是 React Router 数据功能的基础,它们定义了

  • 数据加载
  • 操作
  • 重新验证
  • 错误边界
  • 等等

本指南快速概述了路由对象的每个功能。

Component

路由对象中的 Component 属性定义了当路由匹配时将渲染的组件。

createBrowserRouter([
  {
    path: "/",
    Component: MyRouteComponent,
  },
]);

function MyRouteComponent() {
  return (
    <div>
      <h1>Look ma!</h1>
      <p>
        I'm still using React Router after like 10 years.
      </p>
    </div>
  );
}

unstable_middleware

路由中间件在导航前后按顺序运行。这为您提供了一个统一的地方来执行诸如日志记录和身份验证之类的操作。next 函数会继续向下执行链,在叶子路由上,next 函数会执行导航的加载器/操作。

createBrowserRouter([
  {
    path: "/",
    unstable_middleware: [loggingMiddleware],
    loader: rootLoader,
    Component: Root,
    children: [{
      path: 'auth',
      unstable_middleware: [authMiddleware],
      loader: authLoader,
      Component: Auth,
      children: [...]
    }]
  },
]);

async function loggingMiddleware({ request }, next) {
  let url = new URL(request.url);
  console.log(`Starting navigation: ${url.pathname}${url.search}`);
  const start = performance.now();
  await next();
  const duration = performance.now() - start;
  console.log(`Navigation completed in ${duration}ms`);
}

const userContext = unstable_createContext<User>();

async function authMiddleware ({ context }) {
  const userId = getUserId();

  if (!userId) {
    throw redirect("/login");
  }

  context.set(userContext, await getUserById(userId));
};

另请参阅

loader

路由加载器在路由组件渲染之前为其提供数据。

import {
  useLoaderData,
  createBrowserRouter,
} from "react-router";

createBrowserRouter([
  {
    path: "/",
    loader: loader,
    Component: MyRoute,
  },
]);

async function loader({ params }) {
  return { message: "Hello, world!" };
}

function MyRoute() {
  let data = useLoaderData();
  return <h1>{data.message}</h1>;
}

另请参阅

action

路由操作允许进行服务器端数据修改,并在从 <Form>useFetcheruseSubmit 调用时自动重新验证页面上的所有加载器数据。

import {
  createBrowserRouter,
  useLoaderData,
  useActionData,
  Form,
} from "react-router";
import { TodoList } from "~/components/TodoList";

createBrowserRouter([
  {
    path: "/items",
    action: action,
    loader: loader,
    Component: Items,
  },
]);

async function action({ request }) {
  const data = await request.formData();
  const todo = await fakeDb.addItem({
    title: data.get("title"),
  });
  return { ok: true };
}

// this data will be revalidated after the action completes...
async function loader() {
  const items = await fakeDb.getItems();
  return { items };
}

// ...so that the list here is updated automatically
export default function Items() {
  let data = useLoaderData();
  return (
    <div>
      <List items={data.items} />
      <Form method="post" navigate={false}>
        <input type="text" name="title" />
        <button type="submit">Create Todo</button>
      </Form>
    </div>
  );
}

shouldRevalidate

加载器数据会在某些事件(如导航和表单提交)后自动重新验证。

此钩子使您可以选择加入或退出默认的重新验证行为。默认行为是经过精心设计的,以避免不必要地调用加载器。

当出现以下情况时,路由加载器会重新验证

  • 其自身的路由参数发生变化
  • URL 搜索参数的任何更改
  • 调用 action 并返回非错误状态码后

通过定义此函数,您可以完全退出默认行为,并可以手动控制何时为导航和表单提交重新验证加载器数据。

import type { ShouldRevalidateFunctionArgs } from "react-router";

function shouldRevalidate(
  arg: ShouldRevalidateFunctionArgs,
) {
  return true; // false
}

createBrowserRouter([
  {
    path: "/",
    shouldRevalidate: shouldRevalidate,
    Component: MyRoute,
  },
]);

ShouldRevalidateFunctionArgs 参考文档 ↗

请注意,默认行为在框架模式中有所不同。

lazy

大多数属性都可以懒加载导入,以减少初始包的大小。

createBrowserRouter([
  {
    path: "/app",
    lazy: async () => {
      // load component and loader in parallel before rendering
      const [Component, loader] = await Promise.all([
        import("./app"),
        import("./app-loader"),
      ]);
      return { Component, loader };
    },
  },
]);

下一步: 数据加载

文档和示例 CC 4.0
编辑