主要
分枝
主要 (6.23.1)開發版
版本
6.23.1v4/5.xv3.x
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 提供。

request

這是正在對您的應用程式進行的 擷取請求 實例。

function loader({ request }) {}

請求?

在載入器接收到「請求」時,這乍看之下可能很奇怪。請想想 <Link> 會執行類似以下程式碼的操作,然後問問自己「這裡預防了什麼預設行為?」。

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

如果沒有 React Router,網路瀏覽器將會對您的伺服器進行要求,但 React Router 會阻止它!React Router 會將要求傳送給您的載入器,而不是瀏覽器將要求傳送給您的伺服器。

最常見的應用案例是在建立 網址 和從中讀取 URLSearchParams

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

請注意,這裡的 API 不是 React Router 特有的,而是標準的網路物件:要求網址URLSearchParams

loader.hydrate

如果您是 伺服器端渲染 並利用 future.v7_partialHydration 旗標進行 部分水化,那麼您可能希望選擇在初始水化時執行一個路徑 loader即使它有水化資料(例如,讓使用者使用水化資料作為快取)。若要在部分水化的情況下強制 loader 在水化時執行,您可以在 loader 函式上設定一個 hydrate 屬性

傳回回應

雖然您可以從一個載入器傳回任何您想要的資料,並從 useLoaderData 取得它,您也可以傳回一個網路 回應

這看起來可能沒有什麼立即的用處,但想想 fetch。由於 fetch 的傳回值是一個回應,而載入器會了解回應,許多載入器可以傳回一個簡單的 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();
  // { some: "thing" }
}

使用 json 工具程式可以簡化這一點,因此您不必自行建構它們。以下一個範例實際上與前一個範例相同

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

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

如果您打算升級到 Remix,從每個載入器傳回回應會讓遷移更順暢。

在載入器中拋出

您可以在載入器中 拋出 以中斷目前的呼叫堆疊(停止執行目前的程式碼),而且 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 文件。