React を使っていると、
「Too many re-renders. React limits the number of renders to prevent an infinite loop.」
というエラーに遭遇することがあります。
これは 無限再レンダー(infinite re-render loop) が発生したときに表示されるもので、React 開発では非常に一般的なトラブルです。
この記事では、現場で特によく発生する「典型パターン」と「正しい対処法」をわかりやすく整理します。
目次
パターン1:レンダー中に setState を呼んでしまう
最も多いパターンです。
❌ NG パターン
const MyComponent = () => {
const [count, setCount] = useState(0);
if (count === 0) {
setCount(1); // ← レンダー中に state 更新 → 無限ループ
}
return <div>{count}</div>;
};
レンダー中に setState が呼ばれると、更新 → レンダー → 更新…となり、無限ループが発生します。
✅ OK パターン(useEffect を使う)
useEffect(() => {
if (count === 0) setCount(1);
}, [count]);
パターン2:useEffect の依存配列ミス
依存配列に 状態を毎回更新してしまう値 を入れていると無限ループになります。
❌ NG
useEffect(() => {
setUser({ name: 'Alice' }); // 毎回新しいオブジェクト → 無限ループ
}, [user]);
user が毎回新しいオブジェクトになるため、依存が変わり続けてループします。
✅ OK(関数形式 / メモ化 / 依存を正しく調整)
useEffect(() => {
setUser((prev) => ({ ...prev, name: 'Alice' }));
}, []);
パターン3:イベントハンドラをレンダー中に直接実行している
❌ NG
<button onClick={setCount(count + 1)}>Click</button>
onClick に渡しているのが関数ではなく「実行結果」なので、レンダーのたびに実行されます。
✅ OK
<button onClick={() => setCount(count + 1)}>Click</button>
パターン4:useMemo / useCallback 依存配列の誤り
依存配列を空にしたいのに、依存が変わり続ける書き方になっているパターン。
❌ NG
const fn = useCallback(() => {
setState(Math.random()); // 依存が変わる → 毎回再生成 → 無限ループの原因に
}, [state]);
✅ OK
const fn = useCallback(() => {
setState((v) => v + 1);
}, []);
パターン5:コンポーネントの props が毎回新しい参照値
親でオブジェクトや関数を inline 生成すると、子が毎回レンダリングされ、そこで更新処理が走るケース。
❌ NG(親)
<Child config={{ theme: 'dark' }} />
🎯 対策(親でメモ化)
const config = useMemo(() => ({ theme: 'dark' }), []);
<Child config={config} />;
まとめ:デバッグ時のチェックリスト
React の「Too many re-renders」が出たら、次を確認しましょう。
- レンダー中に state 更新していないか?
- useEffect の依存配列に “変わり続ける値” を入れていないか?
- イベントハンドラを “実行結果” で渡していないか?
- useMemo / useCallback の依存設定は正しいか?
- 親から渡す props は毎回新しいオブジェクト・関数になっていないか?
これらを押さえておけば、無限再レンダーの大半は防げます。

