Next.jsで学ぶReact講座(完全初心者向け・30日)演習問題・課題 | 第4章:実用的React – useEffect

React Next.js
スポンサーリンク

この課題のねらい

ここからが「実用的な React」に一気に近づくところです。
テーマは useEffect──「画面に表示する以外の処理(=副作用)」を、いつ・どのタイミングで実行するかをコントロールするフックです。

初回表示時だけログを出す
state が変わったときだけ処理を走らせる
依存配列([] の部分)が何を意味しているかを言葉で説明できる

この3つを押さえれば、API 通信・タイマー・イベント登録など、実務でよくある処理の“入口”に立てます。


useEffectの基本イメージ

「副作用」をどこで書くか

useEffect は、ざっくり言うとこういうときに使います。

  • 画面に表示する JSX とは別の処理をしたいとき
    例:API からデータを取る、console.log でログを出す、setInterval でタイマーを動かす、スクロールイベントを登録するなど。
  • そしてそれを「いつ実行するか」を、依存配列でコントロールしたいとき。

形はこうです。

useEffect(() => {
  // ここに「副作用」の処理を書く
}, [依存する値]);
TypeScript

第一引数:実行したい処理(関数)
第二引数:その処理を「いつ実行するか」を決めるための配列(依存配列)。

この「依存配列」が、今回の挑戦課題の主役です。


必須課題① 初回表示時にconsole.log

「マウント時に一度だけ」実行するuseEffect

まずは一番シンプルなパターンから。
「コンポーネントが画面に初めて表示されたときに一度だけ console.log を出す」例です。

"use client";

import { useEffect } from "react";

export default function EffectExample() {
  useEffect(() => {
    console.log("コンポーネントが初回表示されました");
  }, []); // ← ここがポイント

  return (
    <main style={{ padding: "24px", fontFamily: "sans-serif" }}>
      <h1>useEffect 初回表示の例</h1>
      <p>コンソールを開いてログを確認してみてください。</p>
    </main>
  );
}
TSX

ここでの重要ポイントは「依存配列が空の []」というところです。

  • [] を渡すと、「初回レンダリング時に一度だけ実行」になります。
  • つまり、「マウント時だけ実行したい処理」(初回データ取得、初期設定など)を書く場所として使えます。

ブラウザの DevTools を開いて Console タブを見ると、
ページを開いたタイミングで一度だけログが出ているはずです。


必須課題② state変更時に処理実行

「特定のstateが変わったときだけ」動くuseEffect

次は、「state が変わったときにだけ処理を走らせる」パターンです。
カウンターを例にしてみます。

"use client";

import { useEffect, useState } from "react";

export default function CounterWithEffect() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("count が変わりました:", count);
  }, [count]); // ← count を依存配列に入れる

  function handleIncrement() {
    setCount((prev) => prev + 1);
  }

  return (
    <main style={{ padding: "24px", fontFamily: "sans-serif" }}>
      <h1>useEffect と state の連動</h1>
      <p>現在のカウント: {count}</p>
      <button onClick={handleIncrement}>+1</button>
      <p style={{ marginTop: "8px" }}>
        ボタンを押すたびに、コンソールにログが出ます。
      </p>
    </main>
  );
}
TSX

ここでの流れを言葉で追ってみます。

  • 画面が初めて表示される(count = 0
    useEffect が一度実行され、「count が変わりました: 0」とログが出る。
  • ボタンを押して setCount が呼ばれる
    count が 1 に変わる
    → 再レンダリング後、[count] の依存配列を見て「count が変わった」と判断
    useEffect が再実行され、「count が変わりました: 1」とログが出る。
  • 以降、count が変わるたびに同じ流れ。

ここで大事なのは、

  • 「依存配列に書いた値が変わったときだけ」useEffect が再実行されるというルールです。
  • [count] と書いたので、「count が変わったときだけ」この effect が動きます。

もし依存配列を省略すると、すべてのレンダリング後に毎回実行されます。
ログを出すだけならまだしも、API 通信などを毎回やると大変なことになるので、
「いつ実行したいか」を意識して依存配列を書くのが超重要です。


挑戦課題 useEffectの依存配列を説明

依存配列とは何か

依存配列(Dependency Array)は、
「この useEffect は、どの値に“依存”しているかを React に教えるためのリスト」です。

React はこの配列を見て、

  • その中のどれかが前回から変わった → effect を再実行
  • 何も変わっていない → effect はスキップ

という判断をします。

よく言われる「黄金ルール」は、

useEffect の中で使っている外側の変数・state・props は、依存配列に入れる。

というものです。

3つの代表的なパターン

依存配列の書き方には、代表的に 3 パターンあります。

依存配列なし(省略)

useEffect(() => {
  console.log("毎回実行される");
});
TypeScript
  • すべてのレンダリング後に毎回実行される。
  • ログやデバッグならまだしも、重い処理を書くとパフォーマンスに悪影響が出やすいです。

空配列 []

useEffect(() => {
  console.log("初回だけ実行される");
}, []);
TypeScript
  • 初回レンダリング時に一度だけ実行される。
  • 初期データ取得・一度だけの設定処理などに使う。

特定の値を入れる [count, userId, ...]

useEffect(() => {
  console.log("count が変わったときだけ実行される");
}, [count]);
TypeScript
  • count が変わったときだけ effect が再実行される。
  • 「この処理はこの値に紐づいている」と明示するイメージです。

なぜ依存配列がそんなに大事なのか

依存配列を正しく書かないと、次のような問題が起きます。

  • 必要以上に何度も effect が走ってしまい、パフォーマンスが悪くなる。
  • 逆に、本当は再実行してほしいのに依存配列に入れ忘れて、古い値のまま処理してしまう(いわゆる「stale state」)。
  • setState を使った処理と組み合わせると、依存配列のミスで無限ループになることもある。

だからこそ、React の公式や lint は、

useEffect の中で使っている外側の値は、基本的に全部依存配列に入れよう。

と強く言っています。
警告が出たら「うるさいな」ではなく、「なぜそれを入れろと言っているのか?」を考えるクセをつけると、一気にレベルが上がります。


まとめ:useEffectでつかんでほしいこと

この課題で本当に押さえてほしいのは、次の感覚です。

  • useEffect は「画面表示とは別の処理(副作用)」を書く場所。
  • 依存配列で「いつ実行するか」をコントロールする。
    • [] → 初回だけ
    • [count] → count が変わったときだけ
    • 省略 → 毎回
  • 「useEffect の中で使っている外側の値は、依存配列に入れる」が基本ルール。

ここが腑に落ちると、

  • 初回表示時に API からデータを取る
  • 特定の state が変わったときだけローカルストレージに保存する
  • ウィンドウサイズの変化に応じてレイアウトを変える

といった“実用的な React の動き”を、自分の頭で設計できるようになっていきます。

タイトルとURLをコピーしました