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
文件。