💡 Tips

React useEffectが無限ループする原因と直し方|依存配列の落とし穴

useEffect の中で state を更新したら、再レンダリングが止まらなくなった——React 初心者が必ず一度は踏む無限ループだ。結論から言うと、原因のほとんどは依存配列の指定ミスにある。仕組みと直し方を整理する。

なぜ無限ループするのか

useEffect は、依存配列の値が変わるたびに実行される。その中で state を更新すると再レンダリングが起き、依存が「変わった」と判定されると、また effect が走る——この連鎖が無限ループだ。

// ❌ 依存配列が無いと毎回実行 → setCount で再レンダリング → また実行…
useEffect(() => {
  setCount(count + 1);
});

① 依存配列を正しく指定する

「いつ実行したいか」を依存配列で明示する。マウント時に1回だけなら空配列。

// ✅ マウント時に1回だけ
useEffect(() => {
  fetchData();
}, []);

② オブジェクト・配列・関数の罠

依存配列にオブジェクトや関数を入れると、毎レンダリングで「別物」と判定されてループしやすい。JavaScript では {} !== {} だからだ。

// ❌ options は毎回新しいオブジェクト → 毎回実行
const options = { limit: 10 };
useEffect(() => { load(options); }, [options]);

対処: useMemo / useCallback で参照を固定する

const options = useMemo(() => ({ limit: 10 }), []);
const load = useCallback(() => { /* ... */ }, []);
useEffect(() => { load(options); }, [load, options]);

参照を安定させれば、不要な再実行が止まる。

③ state更新は条件をつける

effect 内で state を更新するなら、更新が止まる条件を必ず入れる。

useEffect(() => {
  if (count < 10) setCount((c) => c + 1);
}, [count]);

デバッグのコツ

無限ループに陥ったら、effect の中に console.log を1行入れて何が毎回変わっているかを観察する。依存配列の各値をログに出すと、犯人(毎回別物になる値)がすぐ見つかる。

モダンJavaScriptの基本から始める React実践の教科書 (最新ReactHooks対応)
📚 おすすめ書籍

モダンJavaScriptの基本から始める React実践の教科書 (最新ReactHooks対応)

参考価格¥2,574(税込)

ReactのHooks設計を深く理解するための一冊

Amazonで最新価格をチェック

まとめ

  • 無限ループの主因は依存配列の指定ミス
  • マウント時1回なら空配列 []
  • オブジェクト・関数は毎回別物判定。useMemo/useCallback で参照固定
  • effect内のstate更新は停止条件を入れる