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
: アクション完了後、ページのローダーを再実行中