【ITニュース解説】⚡ Optimizing React Performance with React.memo (Real-Time Example)
2025年09月12日に「Dev.to」が公開したITニュース「⚡ Optimizing React Performance with React.memo (Real-Time Example)」について初心者にもわかりやすく解説しています。
ITニュース概要
React.memoは、Reactアプリのパフォーマンスを上げる機能だ。親が再描画されても、子コンポーネントの受け取るデータ(props)が変わらなければ、子の再描画を止める。これにより、無駄な処理を減らし、アプリを速くする。静的なpropsを渡す子に使うと効果的だ。
ITニュース解説
Reactは、ユーザーインターフェースを効率的に構築するためのJavaScriptライブラリである。Reactでアプリケーションを開発する際、パフォーマンスの最適化は非常に重要な要素となる。特に、アプリケーションが複雑になり、多くのコンポーネントが連携するようになると、パフォーマンスの低下がユーザー体験に大きく影響することがある。その中で、React.memoはコンポーネントの不必要な再レンダリングを防ぎ、アプリケーションの速度を向上させる強力なツールとして活用される。
Reactアプリケーションは、データ(状態やプロパティ)が変更されると、その変更を画面に反映するために「再レンダリング」という処理を行う。これは、変更された部分だけでなく、関連するコンポーネントもまとめて再レンダリングされることがある。しかし、場合によっては、データが変わっていないにも関わらず、親コンポーネントの変更に引きずられて子コンポーネントまで再レンダリングされてしまうことがある。これが「不必要な再レンダリング」であり、アプリケーションのパフォーマンスを低下させる主な原因の一つとなる。
具体的なシナリオでこの問題を考えてみよう。例えば、「親」コンポーネントが二つの状態、count(数値)と text(文字列)を持っているとする。この親コンポーネントは、「子」コンポーネントを内包しており、子コンポーネントには常に同じ静的なプロパティ、例えば value="Static Prop" を渡していると仮定する。この時、もしユーザーが「カウントを増やす」ボタンをクリックして親コンポーネントの count の状態だけを変更した場合、親コンポーネントは新しい count の値に基づいて再レンダリングされる。しかし、ここで問題が発生する。子コンポーネントに渡されているプロパティ value="Static Prop" は一切変更されていないにも関わらず、親コンポーネントが再レンダリングされたことで、子コンポーネントも不必要に再レンダリングされてしまうのである。この挙動は、開発ツール(例えばブラウザのコンソール)で確認すると、子コンポーネントが何度もレンダリングされているログを見つけることができる。これは、特に複雑な子コンポーネントであったり、子コンポーネントがさらに多くの子コンポーネントを持っている場合に、処理の遅延やユーザーインターフェースの反応速度の低下を引き起こす可能性がある。
このような不必要な再レンダリングの問題を解決するために登場するのが、React.memoである。React.memoは、特定のコンポーネントを「メモ化」するための機能を提供する。メモ化とは、ある関数やコンポーネントの計算結果やレンダリング結果を記憶(キャッシュ)しておき、同じ入力が与えられた場合には、再度計算やレンダリングを行わずに記憶しておいた結果を再利用する最適化手法のことである。
React.memoを子コンポーネントに適用する方法は非常にシンプルである。子コンポーネントの定義をReact.memo()でラップするだけでよい。例えば、const ChildComponent = React.memo((props) => { /* ... */ }); のように記述する。これにより、Reactは子コンポーネントに対して特別な指示を受け取る。「このコンポーネントは、渡されるプロパティが前回から変更されていない限り、再レンダリングを行う必要はない」という指示である。
このReact.memoを適用した状態で、先ほどの「親」コンポーネントと「子」コンポーネントのシナリオを再度見てみよう。親コンポーネントの count の状態だけを変更するために「カウントを増やす」ボタンをクリックする。親コンポーネントは count の変更を受けて、期待通りに再レンダリングされる。しかし、React.memoでラップされた子コンポーネントは異なる挙動を示す。Reactは子コンポーネントに渡されているプロパティをチェックし、それが前回レンダリングされた時と全く同じであると判断する。結果として、子コンポーネントは再レンダリングされることなく、以前の表示状態がそのまま維持される。開発ツールのコンソールログを確認すると、親が何度もレンダリングされている間も、子は一度しかレンダリングされていないことが明確に確認できるだろう。これにより、無駄な処理が削減され、アプリケーション全体のパフォーマンスが向上する。
React.memoを使用することによる主な利点はいくつか挙げられる。まず、最も直接的な利点は、子コンポーネントの不必要な再レンダリングを防止できることである。これにより、CPUの使用率が減少し、アプリケーションの応答性が向上する。特に大規模なコンポーネントツリー、つまり多くのコンポーネントが階層的に配置されているような複雑なアプリケーションにおいて、この効果は顕著に現れる。React.memoは、渡されるプロパティが同じであれば常に同じ出力結果を生成する「純粋なコンポーネント」と非常に相性が良い。このようなコンポーネントでは、プロパティが変更されない限り再レンダリングする必要が全くないため、React.memoの効果を最大限に引き出すことができる。
ここで、Reactのパフォーマンス最適化機能としてよく似た名前を持つ useMemo と React.memo の違いについても触れておく必要がある。この二つは名前が似ているため混同されがちだが、それぞれ異なる目的と適用範囲を持つ。useMemo は、コンポーネント内部で行われる特定の計算や値の生成処理をメモ化するために使用される。例えば、複雑なデータのフィルタリングやソートなど、時間のかかる計算結果をキャッシュし、その計算を何度も繰り返さないようにする場合に useMemo が役立つ。一方、React.memo は、コンポーネントそのものをメモ化する。これは、コンポーネント全体が、渡されるプロパティが変更されない限り再レンダリングをスキップするように指示するものである。つまり、useMemo は「コンポーネント内の特定の『値』や『計算』を最適化」するのに対し、React.memo は「コンポーネント全体の『再レンダリング』を最適化」する、という明確な違いがある。
結論として、もし子コンポーネントに静的なプロパティ、あるいはほとんど変更されることのないプロパティを渡しているのであれば、React.memoは非常にシンプルかつ効果的な方法で、無駄な再レンダリングを回避し、アプリケーションのパフォーマンスを大幅に改善できる。特に、ユーザーインターフェースが複雑になるにつれて、このような小さな最適化の積み重ねが、最終的なユーザー体験に大きな差を生み出すことになる。システムエンジニアを目指す上で、このようなパフォーマンス最適化の技術は、効率的で高品質なソフトウェアを開発するために不可欠な知識となるだろう。