React Router v7 已發布。 查看文件
全端資料流
本頁內容

全端資料流程

Remix 的主要功能之一是它自動使您的 UI 與持久性伺服器狀態保持同步的方式。它分為三個步驟

  1. 路由載入器向 UI 提供資料
  2. 表單將資料發佈到更新持久狀態的路由動作
  3. 頁面上的載入器資料會自動重新驗證

路由模組匯出

讓我們考慮一個使用者帳戶編輯路由。該路由模組有三個匯出,我們將填寫並討論它們

export async function loader() {
  // provides data to the component
}

export default function Component() {
  // renders the UI
}

export async function action() {
  // updates persistent data
}

路由載入器

路由檔案可以匯出一個 loader 函數,該函數向路由組件提供資料。當使用者導航到匹配的路由時,資料會先載入,然後才渲染頁面。

import type { LoaderFunctionArgs } from "@remix-run/node"; // or cloudflare/deno
import { json } from "@remix-run/node"; // or cloudflare/deno

export async function loader({
  request,
}: LoaderFunctionArgs) {
  const user = await getUser(request);
  return json({
    displayName: user.displayName,
    email: user.email,
  });
}

export default function Component() {
  // ...
}

export async function action() {
  // ...
}

路由組件

路由檔案的預設匯出是渲染的組件。它使用 useLoaderData 讀取載入器資料

import type { LoaderFunctionArgs } from "@remix-run/node"; // or cloudflare/deno
import { json } from "@remix-run/node"; // or cloudflare/deno
import { useLoaderData, Form } from "@remix-run/react";

export async function loader({
  request,
}: LoaderFunctionArgs) {
  const user = await getUser(request);
  return json({
    displayName: user.displayName,
    email: user.email,
  });
}

export default function Component() {
  const user = useLoaderData<typeof loader>();
  return (
    <Form method="post" action="/account">
      <h1>Settings for {user.displayName}</h1>

      <input
        name="displayName"
        defaultValue={user.displayName}
      />
      <input name="email" defaultValue={user.email} />

      <button type="submit">Save</button>
    </Form>
  );
}

export async function action() {
  // ...
}

路由動作

最後,當提交表單時,會呼叫與表單的 action 屬性匹配的路由上的動作。在本例中,它是相同的路由。表單欄位中的值將在標準的 request.formData() API 上可用。請注意,輸入上的 name 屬性與 formData.get(fieldName) getter 相關聯。

import type {
  ActionFunctionArgs,
  LoaderFunctionArgs,
} from "@remix-run/node"; // or cloudflare/deno
import { json } from "@remix-run/node"; // or cloudflare/deno
import { useLoaderData, Form } from "@remix-run/react";

export async function loader({
  request,
}: LoaderFunctionArgs) {
  const user = await getUser(request);
  return json({
    displayName: user.displayName,
    email: user.email,
  });
}

export default function Component() {
  const user = useLoaderData<typeof loader>();
  return (
    <Form method="post" action="/account">
      <h1>Settings for {user.displayName}</h1>

      <input
        name="displayName"
        defaultValue={user.displayName}
      />
      <input name="email" defaultValue={user.email} />

      <button type="submit">Save</button>
    </Form>
  );
}

export async function action({
  request,
}: ActionFunctionArgs) {
  const formData = await request.formData();
  const user = await getUser(request);

  await updateUser(user.id, {
    email: formData.get("email"),
    displayName: formData.get("displayName"),
  });

  return json({ ok: true });
}

提交與重新驗證

當使用者提交表單時

  1. Remix 通過 fetch 將表單資料傳送到路由動作,並且可以通過諸如 useNavigationuseFetcher 之類的 hook 獲得待處理的狀態。
  2. 在動作完成後,會重新驗證載入器以取得新的伺服器狀態。
  3. useLoaderData 從伺服器返回更新的值,並且待處理的狀態會返回到閒置狀態。

通過這種方式,UI 會與伺服器狀態保持同步,而無需編寫任何用於同步的程式碼。

除了 HTML 表單元素之外(例如,響應拖放或 onChange 事件),還有多種提交表單的方式。此外,還有很多關於表單驗證、錯誤處理、待處理狀態等內容需要討論。我們稍後將討論所有這些內容,但這就是 Remix 中資料流程的要點。

JavaScript 載入前

當您從伺服器傳送 HTML 時,最好在 JavaScript 載入之前就使其正常工作。Remix 中典型的資料流程會自動執行此操作。流程是相同的,但瀏覽器會執行一些工作。

當使用者在 JavaScript 載入之前提交表單時

  1. 瀏覽器將表單提交到動作(而不是 fetch),並且瀏覽器的待處理狀態會啟動(旋轉的圖示)
  2. 在動作完成後,會呼叫載入器
  3. Remix 渲染頁面並將 HTML 發送到瀏覽器
文件和範例根據 MIT