React Hooks入門

Reactのコア機能であるHooksの仕組みを、useStateやuseEffectのライフサイクル、およびカスタムフックの作成まで体系的に学びます。

学習をスタートする

ロードマップ

1

useState と useEffect のライフサイクル

React の機能である Hooks(フック) は、関数コンポーネントの中で状態管理や副作用(API通信、DOM操作など)を扱うための仕組みです。 第1章では、最も頻繁に使用される useState と useEffect を取り上げ、コンポーネントがどのように「レンダリング」され、「副作用が実行されるか」というライフサイクルの流れを図解で学びます。 1. useState による状態管理の基本 useState は、コンポーネント内に「状態(State)」を持たせるためのフックです。状態が更新されると、Reactはコンポーネントを再レンダリング(再描画)します。 * count (状態変数): 現在保持されている値です。 * setCount (更新関数): 値を更新するための関数です。これを使って値を変更すると、Reactに再レンダリングがトリガーされます。 2. useEffect のライフサイクルと実行タイミング useEffect は、レンダリング結果が画面に反映された「後」に実行される副作用(Side Effect)を定義します。 実行の流れ(ライフサイクル) 依存配列(Dependencies)による制御 useEffect の第2引数に渡す配列によって、実行タイミングを制御できます。 依存配列の指定 実行されるタイミング 指定なし (useEffect(() => {})) 毎回のレンダリング後 に常に実行される 空の配列 (useEffect(() => {}, [])) 初回のマウント時(画面表示時)のみ 実行される 値あり (useEffect(() => {}, [count])) 初回マウント時 & count の値が変わったときのみ 実行される 3. クリーンアップ関数(Cleanup)の重要性 useEffect 内でイベントリスナーの登録やタイマーの設置(setInterval)を行った場合、コンポーネントが消える(アンマウント)前や、次の副作用が実行される前に、それらを解除(クリーンアップ)する必要があります。 これを怠ると、メモリリーク や予期しないバグの原因になります。 クリーンアップの書き方 コンポーネブラウザ上で非表示になる際、Reactは自動的にこの返された関数(() => clearInterval(intervalId))を呼び出して、タイマーをストップします。 次のチャプターでは、これらを応用して独自のロジックを切り出す「カスタムフック」について学びます!

2

カスタムフックによるロジックの共通化

Reactアプリケーションが成長するにつれ、複数のコンポーネントで「同じ状態管理と副作用の組み合わせ」を使いたいケースが出てきます。 第2章では、React標準のフックを組み合わせて独自のフックを作る カスタムフック(Custom Hooks) の設計方法とメリットについて学びます。 1. カスタムフックとは? カスタムフックは、「状態(State)や副作用(Effect)を伴う再利用可能なロジック」を切り出したJavaScriptの関数 です。 名前は必ず use から始めるというルール(例: useWindowSize)があり、関数内部でReact標準のフック(useState や useEffect など)を自由に呼び出すことができます。 * メリット: 1. UIとロジックの分離: コンポーネントが「見た目(JSX)」に集中でき、コードの見通しが良くなります。 2. 再利用性の向上: 同じロジックを複数のコンポーネントで共有できます。 3. 単体テストの容易さ: Reactフックのロジックだけを独立してテストできます。 2. 実用的なカスタムフックの作成例 例1: 画面サイズを追跡する useWindowSize レスポンシブデザインで、JavaScript側で画面幅(モバイルかデスクトップかなど)を判定したい場合に非常に役立ちます。 コンポーネントでの使用例 3. カスタムフック設計のルール カスタムフックを作る際は、以下のルールを守る必要があります。 1. 命名規則: 必ず use から始める(これにより、Reactのリンターや実行エンジンが「これはフックである」と正しく認識し、フックのルールを検証できます)。 2. フックの呼び出し制限: ループや条件分岐(if 文)、あるいはネストされた関数の中でフックを呼び出してはいけません。常にコンポーネントやカスタムフックの「最上位(トップレベル)」でのみ呼び出します。 3. 状態は共有されない: 同じカスタムフックを2つのコンポーネントで呼び出しても、それらの「状態(State)」は完全に独立 しています(ロジックの書き方は共有されますが、状態自体は共有されません)。状態そのものを共有したい場合は、React Context や状態管理ライブラリを使用します。 カスタムフックを使うことで、複雑なReactコンポーネントをシンプルに保ち、保守性の高いきれいなコードを書くことができます。積極的に活用していきましょう!

3

useMemo と useCallback による最適化

Reactアプリケーションの規模が大きくなると、コンポーネントの不要な再レンダリングによるパフォーマンス低下が問題になることがあります。本章では、再レンダリングを最適化するための強力なフックである useMemo と useCallback、および React.memo の正しい使い方とアンチパターンを学びます。 1. React の再レンダリングのトリガー Reactコンポーネントが再レンダリングされる主なタイミングは以下の3つです。 1. State (状態) の更新: 自身の useState や useReducer の値が変わったとき。 2. Props (プロパティ) の変更: 親コンポーネントから渡される値が変わったとき。 3. 親コンポーネントの再レンダリング: 親が再レンダリングされると、子は Props に変化がなくても デフォルトですべて再レンダリングされます。 2. useMemo と useCallback の違いと仕組み 両者とも、「前回の計算結果(または関数定義)をメモリに保存(メモ化)しておき、依存配列の値が変わらない限り再利用する」 ためのフックです。 * useMemo: 計算結果の 「値」 をメモ化します。 * useCallback: 「関数自体」 をメモ化します。 関数の同一性と useCallback の必要性 JavaScriptにおいて、インラインで定義された関数は、レンダリングのたびに 「新しい参照(新しいインスタンス)」 として再生成されます。 そのため、子コンポーネントに関数を渡す場合、毎回新しい関数が渡されることになり、子が不要に再レンダリングされてしまいます。これを防ぐために useCallback を使って関数の参照を固定します。 3. 最適化の流れ(図解) 親コンポーネントが再レンダリングされたとき、React.memo と useCallback がどのように無駄な子の再レンダリングを防ぐかを整理します。 ※ 注意: 子コンポーネントに React.memo を適用していない場合、親が渡す関数を useCallback でラップしても、子は強制的に再レンダリングされてしまいます。useCallback は React.memo と組み合わせて初めて効果を発揮します。 4. 具体的なコード例 悪い例(不要な最適化) useMemo や useCallback の実行、および依存関係の比較自体にもわずかなオーバーヘッドがかかります。そのため、以下のような単純な処理をメモ化するのは逆効果(アンチパターン)です。 良い例(適切な最適化) 1. 重い計算処理を実行する場合 2. React.memo 化された子コンポーネントに、オブジェクトや関数を Props として渡す場合 まとめ * useMemo は重い計算結果(値)を保存し、useCallback は関数の参照を保存する。 * useCallback は、React.memo でメモ化された子コンポーネントに関数を渡すとき に使用する。 * 安易なメモ化はコードを複雑にし、オーバーヘッドを増やすため、パフォーマンス計測の根拠に基づいて適切に適用する。

4

React 19 新機能と Concurrent Hooks

React 19 では、非同期処理(Actions)とフォームの状態管理をネイティブにサポートするための強力な Hooks が追加されました。これらにより、以前は useState や useEffect、手動のローディング制御を組み合わせて書いていた複雑な非同期ロジックを、シンプルかつ安全に記述できるようになります。 本章では、React 19 のコア機能である新しい Hooks と use API の仕組み・使い方を学びます。 1. React 19 における「Actions」の概念 React 19 では、データを更新する非同期関数を 「Action(アクション)」 と呼びます。 Action を呼び出すと、React は自動的に以下の処理をバックグラウンドで開始します。 * 自動ローディング管理: 非同期処理の開始から終了まで、ローディング状態を自動追跡します。 * 状態の自動同期: UI の更新処理とデータフェッチの競合を防ぎます。 * エラーハンドリング: 境界(Error Boundary)へのスムーズなエラー伝播。 2. 新しい 3 つのフォーム関連 Hooks ① useActionState (旧 useFormState) フォームのアクション(非同期処理)を実行し、その「実行結果」「ローディング状態(isPending)」「アクション関数」を返します。 ② useFormStatus 親子コンポーネント間で、親 の送信ステータスをコンテキスト経由で取得します。これにより、サブミットボタンを別コンポーネント化しても、フォームの送信状態に応じてボタンを非活性化するなどの制御が簡単になります。 [!IMPORTANT] useFormStatus は、 の内側に配置された子コンポーネントの中で使用する必要があります。同一コンポーネントの useFormStatus は親フォームの情報を検知できません。 ③ useOptimistic サーバーの処理完了を待つ前に、UI を一時的に「成功した想定のデータ(楽観的データ)」で更新します。レスポンス時間をゼロに見せることで、極めて滑らかな UX を実現します。 3. 楽観的アップデート(Optimistic UI)のデータフロー(図解) useOptimistic を用いた楽観的アップデートの処理フローは以下のようになります。 4. use API によるリソースの読み込み React 19 では、新しい use API が追加されました。これは use という新しい組み込み関数で、レンダリング中に直接 Promise や Context を読み込む ことができます。 従来の Hooks とは異なり、use は if 文の中や for ループの中で条件付きで呼び出すことが可能です。 Promise を読み込む(データの非同期読み込み) まとめ * React 19 は非同期のデータ更新(Actions)をネイティブで追跡し、ローディングとエラー制御を自動化する。 * useActionState はフォームのアクション結果と isPending 状態を一体として管理できる。 * useFormStatus は子コンポーネントから直接、所属する親フォームの送信状態にアクセスできる。 * useOptimistic はサーバーのレスポンスを待たずにUIを変更し、ユーザーの体感速度を最大化する。 * use API は if やループの中でも使用可能で、Promise や Context を動的に読み込む新しい手段を提供する。

5

高度なフックとReact 19のデータ処理

Reactアプリケーションの複雑度が増すにつれて、単純な useState と useEffect だけでは、パフォーマンスやデータ更新のUX(ユーザー体験)を良好に保つことが難しくなります。特にUIのレスポンス性を損なわずに非同期データ処理を行うため、ReactはトランジションAPIやReact 19で新たなフックを導入しました。 第5章では、アプリケーションを次のレベルに引き上げる高度なフックとReact 19の新機能について学びます。 1. トランジションAPI (useTransition / useDeferredValue) 通常、Reactの状態(state)が変わると、Reactは即座に再レンダリングを実行し、完了するまでブラウザの描画をブロックします。そのため、重い処理があると画面がフリーズしたように感じられます。 useTransition は、状態更新の優先度を「緊急ではない(Transition)」ものとして扱うためのフックです。 * isPending: トランジションがバックグラウンドで処理中(実行中)であるかどうかを示すブーリアン値です。これを使ってローディングスピナーなどを表示できます。 * useDeferredValue: useTransition が「状態更新を行う関数」をラップするのに対し、受け取った「値」自体の更新を遅延させるフックです。 2. React 19 の非同期アクション用フック React 19では、非同期処理(データ送信や更新)に伴うローディング状態やエラーハンドリングを簡素化するために、「アクション(Actions)」 という概念と専用のフックが追加されました。 useActionState (旧 useFormState) フォーム送信などの非同期処理を扱う際、これまで手動で管理していた isLoading や error のステートを自動的に管理します。 useOptimistic (楽観的更新) サーバーへのリクエストが完了する前に、「おそらく成功するだろう」 と予測して、UI上に即座に変更結果を反映させる「楽観的更新(Optimistic Updates)」をシンプルに実現するフックです。 送信が完了すると本番のデータと自動的に置き換わり、失敗した場合は元の状態へ自動ロールバックされます。 3. useSyncExternalStore Reactの管轄外にある外部のデータストア(Reduxなどの独自状態管理ライブラリ、ブラウザの window.navigator.onLine やメディアクエリ window.matchMedia など)と、Reactのコンポーネントの状態を安全に同期・サブスクライブするためのフックです。 useEffect を使った手動同期で発生しがちだった、レンダリング中の一貫性の欠如(テイアリング現象)を防ぎ、並行レンダリング(Concurrent Mode)において安全に動作することを保証します。