アクション

アクションの定義

データの変更は、ルートオブジェクトの action プロパティで定義されたルートアクションを通じて行われます。アクションが完了すると、ページ上のすべてのローダーデータが再検証され、UIをデータと同期させるためのコードを書く必要がなくなります。

import { createBrowserRouter } from "react-router";
import { someApi } from "./api";
 
let router = createBrowserRouter([
  {
    path: "/projects/:projectId",
    Component: Project,
    action: async ({ request }) => {
      let formData = await request.formData();
      let title = formData.get("title");
      let project = await someApi.updateProject({ title });
      return project;
    },
  },
]);

アクションの呼び出し

アクションは、ルートのパスと "post" メソッドを参照することで、<Form> を通じて宣言的に、または useSubmit (あるいは <fetcher.Form>fetcher.submit)を通じて命令的に呼び出されます。

Form を使ったアクションの呼び出し

import { Form } from "react-router";
 
function SomeComponent() {
  return (
    <Form action="/projects/123" method="post">
      <input type="text" name="title" />
      <button type="submit">Submit</button>
    </Form>
  );
}

これによりナビゲーションが発生し、ブラウザの履歴に新しいエントリが追加されます。

useSubmit を使ったアクションの呼び出し

useSubmit を使用して、命令的にフォームデータをアクションに送信できます。

import { useCallback } from "react";
import { useSubmit } from "react-router";
import { useFakeTimer } from "fake-lib";
 
function useQuizTimer() {
  let submit = useSubmit();
 
  let cb = useCallback(() => {
    submit(
      { quizTimedOut: true },
      { action: "/end-quiz", method: "post" },
    );
  }, []);
 
  let tenMinutes = 10 * 60 * 1000;
  useFakeTimer(tenMinutes, cb);
}

これによりナビゲーションが発生し、ブラウザの履歴に新しいエントリが追加されます。

fetcher を使ったアクションの呼び出し

Fetcher を使用すると、ナビゲーションを引き起こさずに(ブラウザ履歴に新しいエントリを追加せずに)アクション(およびローダー)にデータを送信できます。

import { useFetcher } from "react-router";
 
function Task() {
  let fetcher = useFetcher();
  let busy = fetcher.state !== "idle";
 
  return (
    <fetcher.Form method="post" action="/update-task/123">
      <input type="text" name="title" />
      <button type="submit">
        {busy ? "Saving..." : "Save"}
      </button>
    </fetcher.Form>
  );
}

これらには命令的な submit メソッドもあります。

fetcher.submit(
  { title: "New Title" },
  { action: "/update-task/123", method: "post" },
);

詳細については、Fetcher の使用ガイドを参照してください。

アクションデータへのアクセス

アクションは、ルートコンポーネント内で useActionData を通じて、または fetcher を使用している場合は fetcher.data を通じて利用可能なデータを返すことができます。

function Project() {
  let actionData = useActionData();
  return (
    <div>
      <h1>Project</h1>
      <Form method="post">
        <input type="text" name="title" />
        <button type="submit">Submit</button>
      </Form>
      {actionData ? (
        <p>{actionData.title} updated</p>
      ) : null}
    </div>
  );
}

次へ: ナビゲーション