useFetcherを使ったページ遷移なしのサーバーアクション実行

Remixの`useFetcher`フックを使えば、ページ遷移なしでサーバーアクションを実行できます。検索機能やニュースレター登録など、ユーザー体験を損なわずにサーバーサイド処理を行いたい場合に最適です。

広告ここから
広告ここまで

目次

    Remixでは、フォームの送信やデータの取得時に、通常は<Form>コンポーネントやuseSubmitを使用してページ遷移を伴うアクションを実行します。しかし、検索機能やニュースレター登録フォームなど、ページ遷移を伴わずにサーバーサイドの処理を実行したい場合があります。このような場合に便利なのがuseFetcherフックです。

    使用例

    useFetcherを利用することで、ページ遷移なしでサーバーサイドのアクションなどを呼び出せるようになります。ポイントとしては、アクションを呼び出す際のformコンポーネントを、useFetcherで取得できるFormコンポーネントで実装することです。

    function SearchComponent() {
      const fetcher = useFetcher();
    
      return (
        <div>
          <fetcher.Form method="post" action="/api/search">
            <input type="text" name="query" />
            <button type="submit">検索</button>
          </fetcher.Form>
    
          {fetcher.state === "submitting" && <p>検索中...</p>}
    
          {fetcher.data && (
            <ul>
              {fetcher.data.results.map(result => (
                <li key={result.id}>{result.title}</li>
              ))}
            </ul>
          )}
        </div>
      );
    }

    アクション側の実装

    useFetcherを使用する際のサーバーサイドの実装は、通常のRemixのアクションと同じ方法で書くことができます。検索フォームの実装であれば、たとえばこのような実装になります。

    // app/routes/api.search.tsx
    import { ActionFunctionArgs } from "@remix-run/node";
    
    export async function action({ request }: ActionFunctionArgs) {
      // フォームデータの取得
      const formData = await request.formData();
      const query = formData.get("query");
    
      // バリデーション
      if (!query || typeof query !== "string") {
        return Response.json(
          { error: "検索クエリは必須です" },
          { status: 400 }
        );
      }
    
      try {
        // 検索ロジックの実行
        const results = await searchDatabase(query);
    
        // 結果の返却
        return Response.json({ results });
      } catch (error) {
        return Response.json(
          { error: "検索中にエラーが発生しました" },
          { status: 500 }
        );
      }
    }

    useFetcherによる状態管理

    これを利用している場合、fetcher.stateで現在の状態を確認できます。以下の3つのステータスを、コンポーネント側でハンドルしましょう。

    • idle: 何も実行していない
    • submitting: フォームを送信中
    • loading: アクション完了後、ページのローダーを再実行中

    参考文献

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark