はじめに
Reactのコンポーネントは、親コンポーネントが再レンダリングされると、子コンポーネントも再レンダリングされます。
しかし、必要もないのに子コンポーネントまで再レンダリングされると、パフォーマンスに影響が出る場合もあります。
その時に使えるのが、Reactのmemoです。
本記事ではmemoの基本的な使い方について解説します。
memoとは
概要
memoはReactのAPIです。useMemo
という似た処理がありますが、こちらはフックです。
memoはフックではないので、コンポーネントのトップレベル以外の場所でも使用できます。
コンポーネントをmemoでラップすると、その結果が保存されます。
これをメモ化といいます。
コンポーネントのpropsが変化していない場合には、メモ化して取っておいたコンポーネントが使われます。
つまり、親コンポーネントが再レンダリングされても、自身は再レンダリングを行わないません。
コンポーネントに渡されたpropsが変化した場合のみ、新しくコンポーネントをレンダリングします。
基本形
memo(Component, arePropsEqual?)
引数
Component
任意のReactコンポーネントです。
メモ化したいコンポーネントを指定します。
arePropsEqual
省略可能であり、基本的に自分で指定することはないので割愛します。
詳しく知りたい方は以下の公式サイトの説明を参照してください。
戻り値
第1引数に指定したコンポーネントをメモ化したコンポーネントです。
ほぼ完全に同一のコンポーネントが戻り値として渡されます。
propsの値が変わっていない場合、再レンダリングしないというのが唯一の相違点です。
使用例
以下のようなデモを作成しました。
- 親コンポーネントがCount、子コンポーネントが入力フィールドの値を表示する
- Count、入力フィールドの値は親コンポーネントで定義したstate
- 親コンポーネントのレンダリング時は「Rendering Parent」をコンソール出力
- 子コンポーネントのレンダリング時は「Rendering Child - text」を出力
このデモを確認するとわかるように、
「Increment Count」ボタンを押下すると、親コンポーネントのみが再レンダリングされます。
入力フィールドの値が変化すると、親と子のどちらのコンポーネントも再レンダリングされます。
つまり、子コンポーネントの再レンダリングがされない場合があるということです。
これがmemoによる効果です。
実際のコードを確認します。
import { useState, memo } from "react";
// メモ化された子コンポーネント
const ChildComponent = memo(({ name }: { name: string }) => {
console.log(`Rendering Child - ${name}`);
return <div>{name}</div>;
});
// 親コンポーネント
const ParentComponent = () => {
const [count, setCount] = useState(0);
const [name, setName] = useState("John");
console.log("Rendering Parent");
return (
<div>
<h3>Parent Component</h3>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment Count</button>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Change name"
/>
<ChildComponent name={name} />
</div>
);
};
export default ParentComponent;
memo
を使用して、ChildComponentをメモ化しています。
ParentComponentでは、メモ化したChildComponentを使用しています。
ChildComponentは「name」を引数として受け取っています。
つまり、「name」が変更されない限りは、子コンポーネントの再レンダリングがされず、メモ化して保存されていたコンポーネントが使われることになります。
これにより、Countが変化しても子コンポーネントは再レンダリングされませんでした。
memo使用時の注意点
memoは何でもかんでも使えばよい、というものではありません。
使いすぎると、逆にパフォーマンスの低下に繋がります。
今回の例で示したように、入力フィールドを子コンポーネントに渡しており、propsの値が毎度変わるような場合にはmemoを使用するメリットはあまりありません。
子コンポーネントに渡される値がほぼ同一で、かつ頻繁に再レンダリングがされるような場合に有効です。
発展的なmemo
memoとよくセットで使われるのが、useMemo
とuseCallback
というフックです。
useMemo
は値をメモ化し、useCallback
は関数をメモ化します。
これらを組み合わせることで、よりmemoは力を発揮します。
長くなるので本記事では割愛しますが、気になる方は調べてみてください。
まとめ
memo
というReactの機能について紹介しました。
業務でみたことがあるものの、正しい理解ができていなかったので、基本をしっかり抑えることができてよかったです。