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対応)
参考価格¥2,574(税込)
ReactのHooks設計を深く理解するための一冊
Amazonで最新価格をチェックまとめ
- 無限ループの主因は依存配列の指定ミス
- マウント時1回なら空配列
[] - オブジェクト・関数は毎回別物判定。
useMemo/useCallbackで参照固定 - effect内のstate更新は停止条件を入れる