React useEffect
投稿日:2026/02/16
本記事では、Reactの重要なHookである useEffect について解説します。
1. useEffectとは?
useEffectは、副作用(Side Effect)を扱うためのHookです。
副作用とは?
Reactでは「画面を作る処理(レンダリング)」以外の処理を副作用と呼びます。
例えば:
- API通信(データ取得)
- タイマー処理(setInterval)
- イベントリスナー登録
- DOMの直接操作
- ローカルストレージ操作
なぜ分けるの?
Reactは「UIを作ること」に集中する仕組みです。 そのため、画面描画と外部処理を分離する設計になっています。
2. 基本構文
import { useEffect } from "react";
useEffect(() => {
// 実行したい処理
}, []);
構造は次の通りです。
useEffect(実行する関数, 依存配列);
第2引数「依存配列」とは?
「どの値が変わったら再実行するか」を指定する場所です。
これがuseEffect理解の最大のポイントです。
3. 実行タイミングの違い
① 毎回実行される
useEffect(() => {
console.log("毎回実行");
});
→ レンダリングのたびに実行されます。
⚠️ 注意:多くの場合これは意図しない動作になります。
② 初回のみ実行(マウント時)
useEffect(() => {
console.log("初回のみ実行");
}, []);
→ 空配列 [] の場合、最初の1回だけ実行されます。
主な用途:
- API通信
- 初期設定
- 初回データ取得
③ 特定の値が変わった時だけ実行
useEffect(() => {
console.log("countが変わった");
}, [count]);
→ count が変わった時のみ実行されます。
つまり、
「countが更新されたらこの処理を実行する」
という意味になります。
4. 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>
);
}
なぜ [] をつけるの?
もし依存配列を書かなければ、
- データ取得
- setUsers実行
- 再レンダリング
- またfetch実行
という無限ループになります。
そのため、API通信は空配列が基本です。
5. クリーンアップ処理
useEffectは「後片付け」も書けます。
useEffect(() => {
const timer = setInterval(() => {
console.log("1秒ごと");
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
なぜ必要?
もしクリーンアップを書かないと、
- タイマーが増え続ける
- イベントが重複登録される
- メモリリークが発生する
といった問題が起きます。
よく使うケース
- setInterval
- addEventListener
- WebSocket
- サブスクリプション処理
6. よくあるミス
❌ 無限ループ
useEffect(() => {
setCount(count + 1);
}, [count]);
なぜ無限ループになるの?
- countが変わる
- useEffectが実行される
- setCountでcountが更新される
- またuseEffectが実行される
→ 永遠に繰り返す
❌ 依存配列を書き忘れる
useEffect(() => {
console.log(data);
}, []);
→ dataが変わっても再実行されない
初心者は「とりあえず[]を書く」ことがありますが、 本当に初回だけで良いか考えることが重要です。
7. 実務での考え方
① 副作用かどうかを考える
次の質問をしてみてください:
「これはUIを作る処理か?」 「外部とのやり取りか?」
外部処理ならuseEffectです。
② 依存配列は正確に書く
ESLint(react-hooks/exhaustive-deps)に従うのが基本です。
無理に消さないことが重要です。
③ 複雑ならカスタムフックに分離
function useUsers() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("/api/users")
.then(res => res.json())
.then(setUsers);
}, []);
return users;
}
ロジックを分離すると、 コンポーネントがスッキリします。
8. useEffectの本質
useEffectは
「レンダリングが終わった後に実行される処理」
を管理する仕組みです。
Reactの流れ
- state変更
- コンポーネント再実行(再レンダリング)
- DOM更新
- useEffect実行
重要なのは、
useEffectは描画後に実行される
という点です。
9. 実行順
基本の流れ
- state更新
- 再レンダリング
- DOM更新
- useEffect実行
クリーンアップがある場合
- state更新
- 再レンダリング
- 前回のクリーンアップ実行
- DOM更新
- 新しいuseEffect実行
ポイント:
「次のEffectが実行される前に、前回が片付けられる」
React18 StrictModeの場合
開発環境では安全性確認のため
- useEffect実行
- クリーンアップ
- もう一度実行
が起きます。
これはバグではありません。
本番環境では1回のみです。
まとめ
- useEffectは副作用を扱うHook
- 依存配列が最重要ポイント
- API通信は空配列が基本
- クリーンアップは必須
- 無限ループに注意