1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Reactのmemoの基本を抑える

Posted at

はじめに

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」を出力

memo.gif

このデモを確認するとわかるように、
「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とよくセットで使われるのが、useMemouseCallbackというフックです。
useMemoは値をメモ化し、useCallbackは関数をメモ化します。

これらを組み合わせることで、よりmemoは力を発揮します。

長くなるので本記事では割愛しますが、気になる方は調べてみてください。

まとめ

memoというReactの機能について紹介しました。
業務でみたことがあるものの、正しい理解ができていなかったので、基本をしっかり抑えることができてよかったです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?