第 1 章
useState と useEffect のライフサイクル
React の機能である Hooks(フック) は、関数コンポーネントの中で状態管理や副作用(API通信、DOM操作など)を扱うための仕組みです。
第1章では、最も頻繁に使用される useState と useEffect を取り上げ、コンポーネントがどのように「レンダリング」され、「副作用が実行されるか」というライフサイクルの流れを図解で学びます。
1. useState による状態管理の基本
useState は、コンポーネント内に「状態(State)」を持たせるためのフックです。状態が更新されると、Reactはコンポーネントを再レンダリング(再描画)します。
const [count, setCount] = useState<number>(0);
count(状態変数): 現在保持されている値です。setCount(更新関数): 値を更新するための関数です。これを使って値を変更すると、Reactに再レンダリングがトリガーされます。
2. useEffect のライフサイクルと実行タイミング
useEffect は、レンダリング結果が画面に反映された「後」に実行される副作用(Side Effect)を定義します。
実行の流れ(ライフサイクル)
graph TD
subgraph RenderPhase [1. レンダリング・マウント]
Render[コンポーネントが評価される]
DOM[DOMに反映される
画面の更新] Render --> DOM end subgraph EffectPhase [2. 副作用の実行] Effect[useEffect の実行] DOM -->|画面更新の直後| Effect end subgraph UpdatePhase [3. 状態更新 / 再レンダリング] StateChange[状態が変更される] ReRender[再レンダリング実行] DOMUpdate[DOMが更新される] Cleanup[前回のクリーンアップ実行] NewEffect[新しい useEffect の実行] StateChange --> ReRender ReRender --> DOMUpdate DOMUpdate -->|副作用の実行前| Cleanup Cleanup --> NewEffect end subgraph UnmountPhase [4. アンマウント時] Destroy[コンポーネントの破棄] FinalCleanup[クリーンアップの最終実行] Destroy --> FinalCleanup end style RenderPhase fill:#eff6ff,stroke:#3b82f6,stroke-width:2px,color:#1e3a8a style EffectPhase fill:#f0fdf4,stroke:#22c55e,stroke-width:2px,color:#14532d style UpdatePhase fill:#faf5ff,stroke:#a855f7,stroke-width:2px,color:#581c87 style UnmountPhase fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#7c2d12
画面の更新] Render --> DOM end subgraph EffectPhase [2. 副作用の実行] Effect[useEffect の実行] DOM -->|画面更新の直後| Effect end subgraph UpdatePhase [3. 状態更新 / 再レンダリング] StateChange[状態が変更される] ReRender[再レンダリング実行] DOMUpdate[DOMが更新される] Cleanup[前回のクリーンアップ実行] NewEffect[新しい useEffect の実行] StateChange --> ReRender ReRender --> DOMUpdate DOMUpdate -->|副作用の実行前| Cleanup Cleanup --> NewEffect end subgraph UnmountPhase [4. アンマウント時] Destroy[コンポーネントの破棄] FinalCleanup[クリーンアップの最終実行] Destroy --> FinalCleanup end style RenderPhase fill:#eff6ff,stroke:#3b82f6,stroke-width:2px,color:#1e3a8a style EffectPhase fill:#f0fdf4,stroke:#22c55e,stroke-width:2px,color:#14532d style UpdatePhase fill:#faf5ff,stroke:#a855f7,stroke-width:2px,color:#581c87 style UnmountPhase fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#7c2d12
依存配列(Dependencies)による制御
useEffect の第2引数に渡す配列によって、実行タイミングを制御できます。
| 依存配列の指定 | 実行されるタイミング |
|---|---|
指定なし (useEffect(() => {})) |
毎回のレンダリング後 に常に実行される |
空の配列 (useEffect(() => {}, [])) |
初回のマウント時(画面表示時)のみ 実行される |
値あり (useEffect(() => {}, [count])) |
初回マウント時 & count の値が変わったときのみ 実行される |
3. クリーンアップ関数(Cleanup)の重要性
useEffect 内でイベントリスナーの登録やタイマーの設置(setInterval)を行った場合、コンポーネントが消える(アンマウント)前や、次の副作用が実行される前に、それらを解除(クリーンアップ)する必要があります。
これを怠ると、メモリリーク や予期しないバグの原因になります。
クリーンアップの書き方
import { useState, useEffect } from 'react';
export default function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
// 1秒ごとにカウントアップするタイマーをセット
const intervalId = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);
// クリーンアップ関数を返す
return () => {
clearInterval(intervalId); // コンポーネント消滅時や再実行前にタイマーを解除
console.log('タイマーが解除されました');
};
}, []); // 空の配列なので、マウント時に1回だけタイマーをセット
return <div>起動時間: {seconds} 秒</div>;
}
コンポーネブラウザ上で非表示になる際、Reactは自動的にこの返された関数(() => clearInterval(intervalId))を呼び出して、タイマーをストップします。
次のチャプターでは、これらを応用して独自のロジックを切り出す「カスタムフック」について学びます!