React を使い始めると、誰もが一度は遭遇する「useEffect の無限ループ」。私自身も依存配列の指定を忘れたり、意図せず state を更新してしまったりして、画面が固まる経験を何度もしました。
なぜ useEffect は無限ループしてしまうのか?どう書けば防げるのか?
この記事では、初心者でも理解しやすいように、React の内部動作とともに原因と対策を整理して解説します。
React を触り始めると、多くの人が一度は遭遇するのが useEffect の無限ループ です。
私自身も開発中に、
useEffect(() => {})と依存配列を書き忘れて無限ループuseEffect(() => {}, [var])の依存がズレて無限ループ
といった初歩的なミスに何度かハマってきました。
この記事では、実際に起こりやすいパターンと、なぜそうなるのかをシンプルにまとめます。
■ 1. 依存配列を書き忘れると無限ループになる
もっとも多いミスがこれです。
useEffect(() => {
setCount(count + 1); // ← state 更新
});
依存配列 [] がないと、useEffect は 毎回のレンダー後に必ず実行されます。
その中で state を更新すると、再レンダーが起き、また useEffect が走り…
永久ループが完成します。
✔ 正しい書き方(初回だけ動かす)
useEffect(() => {
setCount(count + 1);
}, []);
■ 2. 依存配列に“更新している値”を入れるとループが発生する
たとえば次の例。
useEffect(() => {
setData([...data, "new"]);
}, [data]);
data を更新すると → data が変わる → useEffect が再実行 → また更新…
というループが起きてしまいます。
✔ 対策:関数型アップデートを使う
useEffect(() => {
setData(prev => [...prev, "new"]);
}, []);
prev が常に最新値なので、data を依存に入れる必要がなくなります。
■ 3. 関数が原因で無限ループするパターン
関数は毎レンダーで新しく生成されるため、依存が変わってしまいます。
const update = () => {
setValue(value + 1);
};
useEffect(() => {
update();
}, [update]); // update が毎回変わるので無限ループ
✔ 対策:useCallback で固定する
const update = useCallback(() => {
setValue(v => v + 1);
}, []);
useEffect(() => {
update();
}, [update]);
【Tips】なぜ依存配列を書かないと無限ループするの?
仕組みを一度理解しておくと、一気にミスが減ります。
① useEffect はデフォルトで“毎レンダー後に実行される”
依存配列([])がない場合、React はこう解釈します。
「条件がないなら、毎回実行するしかない」
② useEffect 内で state を更新すると、必ず再レンダーが起きる
useEffect(() => {
setCount(count + 1);
});
これを行うと、
- レンダー
- effect 実行
- state 更新
- 再レンダー
- effect 実行(以下ループ)
という構造が自動的に成立します。
③ 依存配列は“いつ effect を実行するか”を React に伝えるためのもの
[]→ 初回だけ[count]→ count が変わった時だけ
「何も指定しない」という状態が、一番危険なのです。
1行まとめ
依存配列を書かない =「毎回実行して」と命令している。
その中で state を更新すれば、再レンダー → effect → 再レンダーの無限ループが成立する。
■ 4. 無限ループを防ぐためのチェックリスト
- 依存配列の書き忘れはない?
- useEffect 内で更新している値を依存に入れていない?
- 関数を依存にするなら useCallback で固定してる?
- React が変化を追跡できる値だけ依存にしている?
- 初回のみ実行したいなら
[]でOK?
■ まとめ
useEffect の無限ループは
- 依存配列の設定ミス
- 更新対象と依存対象が一致してしまっている
- 関数が毎レンダーで再生成されている
この3つがほぼすべてです。
依存配列には 必要最小限だけ記述する、
そして prev を使った関数型アップデートを活用することで、
ほとんどの無限ループは防げます。

コメント