React 入門:useEffectの実践的な使い方

React でコンポーネントを作っていると、「初回表示時にデータを取得したい」「特定の値が変わったときに処理を実行したい」といった場面に出会います。そんなときに登場するのが useEffect フック です。

今回は、基本から実践的なパターンまでを整理して解説します。


useEffect とは?

useEffect は React Hooks のひとつで、副作用(side effects) を扱うために使います。
「副作用」とは、レンダー以外で行う処理のこと。たとえば:

  • API からデータを取得
  • DOM の操作
  • タイマー処理
  • イベントリスナーの登録・解除

基本の書き方

import { useEffect } from "react";

useEffect(() => {
  // 実行したい処理
  console.log("コンポーネントが描画されました");
});

この場合、コンポーネントが再レンダーされるたびに処理が実行されます。


依存配列(第二引数)の使い方

useEffect は第二引数に「依存配列」を指定できます。
これによって「いつ実行されるか」をコントロールできます。

1. 初回レンダー時だけ実行

useEffect(() => {
  console.log("初回のみ実行される処理");
}, []);

2. 特定の値が変わったときだけ実行

useEffect(() => {
  console.log("countが変わるたびに実行される");
}, [count]);

3. 依存配列なし(毎回実行)

useEffect(() => {
  console.log("レンダーのたびに実行");
});

実践例 1: API データの取得

import { useState, useEffect } from "react";

function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((res) => res.json())
      .then((data) => setUsers(data));
  }, []); // 初回だけ実行

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

ここでは、初回マウント時に一度だけ API リクエストを行っています。


実践例 2: イベントリスナーの登録と解除

useEffect では「クリーンアップ関数」を返すことで、コンポーネントのアンマウント時に処理を実行できます。

import { useEffect } from "react";

function WindowSize() {
  useEffect(() => {
    const handleResize = () => {
      console.log("ウィンドウサイズ:", window.innerWidth);
    };

    window.addEventListener("resize", handleResize);

    // クリーンアップ
    return () => {
      window.removeEventListener("resize", handleResize);
    };
  }, []);

  return <p>ウィンドウのサイズをチェックしてください</p>;
}

こうすることで、不要なイベントリスナーが残ってメモリリークを起こすのを防げます。


実践例 3: タイマー処理

import { useState, useEffect } from "react";

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

  useEffect(() => {
    const id = setInterval(() => {
      setCount((c) => c + 1);
    }, 1000);

    return () => clearInterval(id); // コンポーネント破棄時に解除
  }, []);

  return <p>経過秒数: {count}</p>;
}

setInterval のようなタイマーも、クリーンアップで確実に解除しておくのがポイントです。


よくある注意点

  1. 依存配列の書き忘れ

    • API リクエストで依存配列を省略すると、毎回呼ばれて無限ループになることがある。
    • 必要な依存関係は必ず指定しましょう。
  2. 関数やオブジェクトを依存に含める場合

    • useCallbackuseMemo を使ってメモ化すると無駄な再実行を防げます。
  3. クリーンアップ忘れ

    • イベントリスナーやタイマーは、必ずクリーンアップ関数で解除しておくのが鉄則です。

まとめ

  • useEffect は「副作用」を扱うためのフック
  • 依存配列で「いつ実行するか」を制御できる
  • クリーンアップ関数でリソースを解放するのが大事
  • 実用例は「API 取得」「イベントリスナー」「タイマー」など