React - 第3章:useEffect

React - useEffect

副作用処理を学ぼう

useEffect - 副作用の処理

Reactで、「レンダリング以外の処理」を扱うには、useEffectを使います。


副作用(Side Effect)とは?

副作用とは、「コンポーネントの外の世界に影響を与える処理」のことです。

副作用の例:

  • APIからデータを取得する
  • ブラウザのタイトルを変更する
  • タイマーをセットする
  • ログを記録する

副作用ではないもの:

  • 画面に表示する内容を計算する
  • ボタンクリックでstateを更新する

useEffectの基本

書き方

import { useEffect } from 'react';

useEffect(() => {
  // ここに副作用の処理を書く
}, [依存配列]);

依存配列とは?

依存配列は、「useEffectをいつ実行するか」を決める重要な部分です。

パターン1: 依存配列なし(毎回実行)

useEffect(() => {
  console.log('レンダリングのたびに実行される');
});

→ あまり使わない(無限ループの原因になりやすい)

パターン2: 空の依存配列(最初の1回だけ)

useEffect(() => {
  console.log('最初のレンダリング時だけ実行');
}, []);  // 空の配列

よく使う! データ取得などに使う

パターン3: 依存配列あり(値が変わった時)

const [count, setCount] = useState(0);

useEffect(() => {
  console.log('countが変わった!');
}, [count]);  // countが変わった時だけ実行

よく使う! 特定の値の変化に反応する


依存配列のイメージ図

【空の配列 []】

時間 →
◯初回レンダリング  ×再レンダリング  ×再レンダリング
↓                      
実行!                


【依存配列あり [count]】

count: 0 → 1 → 1 → 2
       ◯   ◯   ×   ◯
       ↓   ↓       ↓
     実行 実行   実行
     (値が変わった時だけ)

実践例1:カウントが変わったらログに記録

import { useState, useEffect } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  const [logs, setLogs] = useState<string[]>([]);

  useEffect(() => {
    // countが変わるたびにログを追加
    const message = `カウントが${count}になりました`;
    setLogs(prev => [...prev, message]);
  }, [count]);  // countが変わった時に実行

  return (
    <div>
      <p>カウント: {count}</p>
      <button onClick={() => setCount(count + 1)}>増やす</button>
      
      <h3>ログ</h3>
      {logs.map((log, i) => <p key={i}>{log}</p>)}
    </div>
  );
}

ポイント:

  • ボタンを押す → countが変わる → useEffectが実行 → ログが追加

実践例2:最初に1回だけデータを取得

import { useState, useEffect } from 'react';

interface User {
  id: number;
  name: string;
}

function UserList() {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // APIからデータを取得
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(res => res.json())
      .then(data => {
        setUsers(data);
        setLoading(false);
      });
  }, []);  // 空配列 = 最初の1回だけ

  if (loading) return <p>読み込み中...</p>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

ポイント:

  • 空の依存配列 [] = 「最初の1回だけ実行」
  • コンポーネントが表示された時にデータを取りに行く

よくある間違い

❌ 依存配列を忘れると無限ループ

// これは無限ループ!
const [count, setCount] = useState(0);

useEffect(() => {
  setCount(count + 1);  // stateを更新
});  // 依存配列がない = 毎回実行

// 毎回実行 → state更新 → 再レンダリング → 毎回実行... ∞

✅ 依存配列を正しく指定

// 正しい例
const [count, setCount] = useState(0);

useEffect(() => {
  console.log('countが変わった:', count);
}, [count]);  // countが変わった時だけ実行

useEffectの実行タイミング

1. コンポーネントがレンダリングされる
2. 画面が更新される
3. useEffectが実行される  ← レンダリングの「後」

useEffectは画面表示をブロックしません。


まとめ

useEffectの基本

  • 副作用(レンダリング以外の処理)を扱う
  • 依存配列で実行タイミングを制御

依存配列のパターン

  • [] → 最初の1回だけ
  • [count] → countが変わった時
  • なし → 毎回(注意!)

よく使う場面

  • APIからデータを取得
  • 値の変化に反応して何かする

次は、TypeScriptとReactを組み合わせた型定義を学びましょう!