はじめに
Reactを学習し始めたばかりの方が陥りやすい問題の一つに「無限レンダリング(無限表示)」があります。
この記事では、無限レンダリングが発生する原因やその対策について解説します。
無限レンダリングとは?
無限レンダリングとは、Reactコンポーネントが何度も再レンダリングされ続ける現象です。
これが発生すると、アプリケーションのパフォーマンスが著しく低下し、最悪の場合、ブラウザがクラッシュすることもあります。
無限レンダリングが発生する原因
無限レンダリングが発生する主な原因は以下のとおりです
- 状態の更新が原因
- 依存配列の誤り
一つずつ見てみましょう。
1.状態の更新が原因
useStateフックを使用して状態を管理する際に、状態の更新がレンダリングのたびに行われると無限ループが発生します。
例えば、以下のようなコードです。
import React, { useState } from 'react';
const ExComponentSky = () => {
const [count, setCount] = useState(0);
setCount(count + 1); // これが無限レンダリングの原因
return <div>{count}</div>;
};
上記は、ExComponentSkyが作成されるとレンダリングが発生 ⇒
setCountにより状態が更新(再レンダリングされる) ⇒
ExComponentSkyでレンダリングが発生したので再びsetCountが実行され状態が更新(再再レンダリング) ⇒
・・・・・というような形です。
この例はわかりやすいので陥ることも少ないかと思いますが、もう少し複雑な親子コンポーネントになると注意が必要です。
2.依存配列の誤り
親コンポーネントで状態管理しているフックを子コンポーネントに渡す例を考えてみます。
★親コンポーネント★
const ParentComponent = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount(prevCount => prevCount + 1);
};
return (
<div>
<h1>回数: {count}</h1>
</div>
);
};
★子コンポーネント★
const ChildComponent = ({ increment }) => {
useEffect(() => {
increment();
}, [increment]);
return (
<div>
<button onClick={increment}>増やす!</button>
</div>
);
};
この例では以下のように処理が行われます。
- 親コンポーネントが初回レンダリングされ、increment関数が生成されます。
- 子コンポーネントがレンダリングされ、useEffectが実行されます。
- useEffect内でincrement関数が呼び出され、countが更新されます。
- 親コンポーネントが再レンダリングされ、新しいincrement関数が生成されます。
- 子コンポーネントが再レンダリングされ、useEffectが再度実行されます。
- このサイクルが無限に続き、無限レンダリングが発生します。
上記は極端な例ですが、複数の関数を経由していたり、親子関係が深いものになればなるほど思わぬ事故を引き起こします。
対策としては、useEffectの依存配列を適切に設定するか、useCallbackというものを使用して、increment関数オブジェクトが再作成されないようにすることが考えられます。
useCallbackは上記の4番が行われないようにすることで無限レンダリングを止める機能を持ちます。
★親コンポーネントの修正例(useCallback)★
const ParentComponent = () => {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []);
return (
<div>
<h1>回数: {count}</h1>
</div>
);
};
もしくは、
★子コンポーネントの修正例(依存配列の見直し)★
const ChildComponent = ({ increment }) => {
useEffect(() => {
increment();
}, []);// 依存配列を空にすると、初回レンダリング時のみ実行されます
return (
<div>
<button onClick={increment}>増やす!</button>
</div>
);
};
まとめ
ReactとTypeScriptを使い始めたばかりの初学者が陥りやすい無限レンダリングの原因と対策について簡単に解説しました。
無限レンダリングを防ぐには、状態の更新や依存配列の設定に注意することが大切です。
これらのポイントを押さえて、React開発を楽しんでみてはいかがでしょうか。

