loader

每个路由都可以定义一个 loader 函数,在渲染之前向路由元素提供数据。

此功能仅在使用数据路由器时有效,请参阅路由器选择

createBrowserRouter([
  {
    element: <Teams />,
    path: "teams",
    loader: async () => {
      return fakeDb.from("teams").select("*");
    },
    children: [
      {
        element: <Team />,
        path: ":teamId",
        loader: async ({ params }) => {
          return fetch(`/api/teams/${params.teamId}.json`);
        },
      },
    ],
  },
]);

当用户在应用程序中导航时,将并行调用下一个匹配路线分支的加载器,并通过useLoaderData将其数据提供给组件。

params

路由参数从动态段解析并传递给加载器。这对于确定加载哪个资源很有用:

createBrowserRouter([
  {
    path: "/teams/:teamId",
    loader: ({ params }) => {
      return fakeGetTeam(params.teamId);
    },
  },
]);

路径中的:teamId被解析并作为同名的params.teamId提供给 loader

request

这是向您的应用程序发出的 Fetch Request 实例。

function loader({ request }) {}
<a
  href={props.to}
  onClick={(event) => {
    event.preventDefault();
    navigate(props.to);
  }}
/>

如果没有 React Router,浏览器会向您的服务器发出请求,但 React Router 阻止了它!React Router 将请求发送给加载器,而不是浏览器将请求发送到服务器。

最常见的用例是创建一个 URL 并从中读取 URLSearchParams

function loader({ request }) {
  const url = new URL(request.url);
  const searchTerm = url.searchParams.get("q");
  return searchProducts(searchTerm);
}

这里的 API 不是特定于 React Router 的,而是标准的web对象:RequestURLURLSearchParams

loader.hydrate

如果你是服务器端渲染,并利用future.v7_partialHydration标志进行部分水合,那么你可能希望在初始水合时运行路由加载器,即使它有水合数据(例如,让用户用水合数据填充缓存)。要强制加载器在部分水合情况下运行水合,您可以在加载器功能上设置水合属性:

Returning Responses

你可以从 loader 返回任何你想要的东西,并从 useLoaderData 访问它,你也可以返回一个web 响应。

这可能看起来没有立竿见影的效果,但考虑一下 fetch。由于 fetch 的返回值是 Response,并且加载器理解响应,因此许多加载器可以返回简单的 fetch!

// an HTTP/REST API
function loader({ request }) {
  return fetch("/api/teams.json", {
    signal: request.signal,
  });
}

// or even a graphql endpoint
function loader({ request, params }) {
  return fetch("/_gql", {
    signal: request.signal,
    method: "post",
    body: JSON.stringify({
      query: gql`...`,
      params: params,
    }),
  });
}

您也可以自己构建响应:

function loader({ request, params }) {
  const data = { some: "thing" };
  return new Response(JSON.stringify(data), {
    status: 200,
    headers: {
      "Content-Type": "application/json; utf-8",
    },
  });
}

React Router 会自动调用response.json(),这样你的组件在渲染时就不需要解析它了:

function SomeRoute() {
  const data = useLoaderData();
}

使用 json 方法可以简化了这一过程,您不必自己构建 Response

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

function loader({ request, params }) {
  const data = { some: "thing" };
  return json(data, { status: 200 });
}

如果您计划升级到 Remix,则从每个加载器返回响应将使迁移更加顺利。

在 loader 中抛出异常

你可以在loader中抛出异常,来跳出当前的调用堆栈(停止运行当前代码),React Router 将沿着错误路径重新启动。

function loader({ request, params }) {
  const res = await fetch(`/api/properties/${params.id}`);
  if (res.status === 404) {
    throw new Response("Not Found", { status: 404 });
  }
  return res.json();
}

有关更多详细信息,请阅读 errorElement 文档。

最后更新于

这有帮助吗?