Reactは、コンポーネントベースのライブラリであり、状態管理やUIの更新を効率的に行うための仕組みを提供しています。しかし、時には無駄な再レンダリングが発生し、アプリケーションのパフォーマンスに悪影響を及ぼすことがあります。
本記事では、Reactにおける無駄な再レンダリングの原因と、それに対する最適な対処法について詳しく解説します。
1. 再レンダリングの基本
Reactのコンポーネントは、以下の条件で再レンダリングされます。
- Stateの変更
- コンポーネント内で
useState
フックを使用している場合、状態が変更されるとそのコンポーネントは再レンダリングされます。
- コンポーネント内で
- Propsの変更
- 親コンポーネントから渡されたpropsが変更されると、子コンポーネントは再レンダリングされます。
- 親コンポーネントの再レンダリング
- 親コンポーネントが再レンダリングされると、その子コンポーネントも無条件に再レンダリングされます。
これらの条件を理解することで、無駄な再レンダリングを防ぐための対策を講じることができます。
2. 無駄な再レンダリングの原因
無駄な再レンダリングが発生する主な原因は以下の通りです。
- 不適切な状態管理
- 状態が頻繁に変更される場合、特に大きなオブジェクトや配列を状態として持つ場合、無駄な再レンダリングが発生しやすくなります。
- 関数の再生成
- コンポーネント内で定義された関数は、コンポーネントが再レンダリングされるたびに新たに生成されます。これにより、子コンポーネントに渡される関数が毎回異なるものとなり、子コンポーネントも再レンダリングされてしまいます。
- Contextの使用
- ReactのContextを使用する際、Providerのvalueが変更されると、その配下にある全てのコンポーネントが再レンダリングされます。これにより、必要のない再レンダリングが発生することがあります。
3. 再レンダリングを防ぐためのテクニック
無駄な再レンダリングを防ぐためには、以下のテクニックを活用することが重要です。
- React.memoの使用
React.memo
を使用することで、propsが変更されない限りコンポーネントの再レンダリングを防ぐことができます。これにより、パフォーマンスが向上します。
- useCallbackの活用
useCallback
フックを使用することで、関数をメモ化し、再レンダリング時に新しい関数が生成されるのを防ぎます。これにより、子コンポーネントへのpropsとして渡す関数が常に同じ参照を持つことができます。
- useMemoの利用
useMemo
を使用して計算結果をメモ化することで、依存する値が変更されない限り再計算を避けることができます。これにより、パフォーマンスが向上します。
以下は、useCallback
とReact.memo
を使用したサンプルコードです。
import React, { useState, useCallback } from 'react';
const ChildComponent = React.memo(({ onClick }) => {
console.log('ChildComponent rendered');
return <button onClick={onClick}>Click me</button>;
});
const ParentComponent = () => {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Button clicked');
}, []);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
<ChildComponent onClick={handleClick} />
</div>
);
};
export default ParentComponent;
この例では、ChildComponent
はReact.memo
でラップされているため、ParentComponent
の状態が変更されても、handleClick
関数がメモ化されているため、無駄な再レンダリングが発生しません。
4. React DevToolsを活用する
無駄な再レンダリングを特定するためには、React DevToolsを活用することが非常に有効です。DevToolsのProfiler機能を使用することで、どのコンポーネントが再レンダリングされているかを視覚的に確認できます。これにより、パフォーマンスのボトルネックを特定し、最適化の手助けとなります。

Profilerを使用する手順は以下の通りです。
- React DevToolsをインストールし、ブラウザの開発者ツールを開きます。
- Profilerタブを選択し、録画を開始します。
- アプリケーションを操作し、再レンダリングが発生する様子を観察します。
- 録画を停止し、どのコンポーネントが再レンダリングされたかを確認します。
この情報をもとに、無駄な再レンダリングを引き起こしているコンポーネントや関数を特定し、最適化を行うことができます。
5. 状態管理の見直し
無駄な再レンダリングを防ぐためには、状態管理の方法を見直すことも重要です。特に、複雑な状態を持つ場合は、状態を適切に分割し、必要な部分だけを更新するように心がけることが大切です。
- 状態の分割
- 大きなオブジェクトや配列を状態として持つ場合、それを複数の小さな状態に分割することで、無駄な再レンダリングを防ぐことができます。
- カスタムフックの利用
- 状態管理をカスタムフックに分離することで、コンポーネントの再レンダリングを最小限に抑えることができます。これにより、状態の変更が必要なコンポーネントだけが再レンダリングされるようになります。
6. まとめ
Reactにおける無駄な再レンダリングは、アプリケーションのパフォーマンスに悪影響を及ぼす可能性があります。再レンダリングの基本を理解し、無駄な再レンダリングを防ぐためのテクニックを活用することで、パフォーマンスを最適化することができます。
特に、React.memo
、useCallback
、useMemo
を適切に使用し、React DevToolsを活用することで、無駄な再レンダリングを特定し、改善することが可能です。