0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React:シリーズ3】最新React 19対応:非同期処理・フォーム管理のNext Generation Hooksとサーバー状態管理

Last updated at Posted at 2025-12-04

この回では、React 19で登場した新しいフックや、現代のReact開発におけるサーバー状態管理のベストプラクティスである TanStack Query について解説します。

💡 React 19 / Server Components時代の最新Hooks

Server Componentsや非同期処理の管理を容易にするために、新しいHooksとコンポーネントが導入されました。

1. use — 非同期データの簡易取得

useフックは、コンポーネント内で PromiseThenable を直接受け取り、非同期処理を簡単に扱えるようにする機能です。

Server Componentsと組み合わせることで、データをprops経由で渡す必要が減り、コードが簡潔になります。

例:

import { use } from "react";

async function fetchUser() {
  const res = await fetch("/api/user");
  return res.json();
}

function UserProfile() {
  const user = use(fetchUser()); // Promise を直接受け取る
  return <p>{user.name}</p>;
}

ポイント

  • Promise が解決されるまで 自動で Suspense の fallback にフォールバックします。
  • Client Component 内でも使用可能ですが、必ず Suspense でラップする必要があります。

2. Suspense — 非同期読み込み UI

非同期データやコンポーネントの読み込み時に、ローディング表示を簡単に実装できるコンポーネントです。use フックと組み合わせることで、データ取得完了まで UI を待機させることができます。

例:

import { Suspense } from "react";

// UserProfileコンポーネントが内部で use を使ってデータを取得していると仮定
<Suspense fallback={<p>Loading user...</p>}>
  <UserProfile /> 
</Suspense>

3. フォーム・アクション管理のためのHooks(React 19)

Server Actionsやフォーム送信時のユーザー体験を向上させるために、以下のHooksが導入されました。

useFormStatus — フォーム送信状態の取得

フォーム送信中かどうかを取得し、UI に反映させるためのフックです。

例:

const { pending } = useFormStatus();

<button type="submit" disabled={pending}>
  {pending ? "送信中..." : "送信"}
</button>

useActionState — アクション実行と state 管理を同時に行う

useFormState が改名されたもので、サーバーアクション実行時の state 変化を管理できます。アクション実行時の状態や結果メッセージをクライアント側で受け取って管理するために使います。

例:

const [state, formAction, pending] = useActionState(action, 0);

<form action={formAction}>
  <button disabled={pending}>+1</button>
</form>

<p>現在の値: {state}</p>

useOptimistic — 楽観的UI(サーバー待たず先にUI更新)

サーバー処理の完了を待たずに 一旦 UI を先に更新する(楽観的更新) ためのフックです。チャット投稿や「いいね」のように、すぐにUIを更新することでレスポンス性を高めます。

例:

const [messages, addOptimisticMessage] = useOptimistic(
  initialMessages,
  (state, newMessage) => [...state, newMessage]
);

function handleSend(message) {
  addOptimisticMessage(message); // UI 先行更新
  submitToServer(message);       // サーバー送信
}

💻 useEffect から卒業 — TanStack Queryでサーバー状態管理の正解を学ぶ

React で API 通信をするとき、昔は useEffect + fetch が定番でしたが、現在は TanStack Query(旧 React Query) がサーバー状態管理のデファクトスタンダードとなっています。

useEffect + fetch の根本的な課題

useEffect は、本来「UIの副作用」を扱うためのHooksであり、以下のようなサーバー状態管理の煩雑なタスクには向いていません。

  1. 状態の肥大化: loading / error / data3つのState を必ず手動で管理する必要がある。
  2. キャッシュの欠如: 毎回再フェッチが実行され、無駄な通信が増える。
  3. 機能の不足: 自動リフェッチ、リトライ、ウィンドウ復帰時の最新化など、モダンな機能はすべて自作が必要。

TanStack Query(useQuery)が解決すること

TanStack Queryは、API通信に関わる面倒な処理のほぼすべてを自動化する サーバー状態の完全管理ツール です。

機能 useEffect TanStack Query
ローディング/エラー管理 手実装 自動
キャッシュ管理 × 自動
複数コンポーネントでデータ共有 ×
ウィンドウ復帰で最新化 ×
リトライ・バックグラウンド更新 ×

実装例の比較(TanStack Query)

useEffectで数十行必要だった処理が、TanStack Queryでは非常にシンプルになります。

import { useQuery } from "@tanstack/react-query";

export default function Users() {
  // data, isLoading, error の状態を自動で受け取る
  const { data, isLoading, error } = useQuery({
    queryKey: ["users"], // データの一意なキー
    queryFn: () => fetch("/api/users").then((res) => res.json())
  });

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error!</p>;

  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

まとめ:状態管理ツールの使い分け

シナリオ 推奨ツール 理由
APIなどサーバーからデータを取得する TanStack Query サーバー状態管理に必要な機能をすべて備えているため。
UI/設定などのグローバル状態 Zustand / Context 非同期に依存しないローカル状態の共有に適しているため。
ローカル状態の管理だけ useState / useReducer / useEffect コンポーネント固有の簡易な状態管理のため。

現代のベストプラクティスは 「Zustand × TanStack Query × Next.js」 の組み合わせが非常に強力です。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?