React.memo で更新制御

React.memoで関数をラップすると、関数にpropsが渡ってくる前に「更新必要そうか?」が確認されるようになります。もちろん、「更新必要なさそう」と判断された場合は前回返されたコンポーネントの結果が使われます。

例。

const Foo = React.memo(props => {
  return <div>{props.text}</div>
});

これは以下と同等です。

const Foo = React.memo(
  props => {
    return <div>{props.text}</div>
  },
  (prevProps, nextProps) => {
    return prevProps.text === nextProps.text;
  }
);

1つ目の引数に渡すのは単に Functional Component ですが、2つ目の引数には前回のpropsと今回のpropsを使って何らかの確認を行う関数を渡します。この関数がfalseを返すと「更新必要そう」と判断されます。

また2つ目の関数は省略可能で、渡さなかった場合は浅い比較での比較(オブジェクトの第一階層同士のチェック)を行う関数になります。

この部分をできるだけデフォルトの浅い比較で済ますためにuseMemouseCallbackなどのフックが役立ちます。直前に生成したオブジェクト値などをプロパティに渡すと、参照同士の比較で常にfalseになってしまいますが、メモ関数から返された値を使うことで場合によってtrueとなる値を取得することができます。つまり、メモ関数によってオブジェクトが同じかどうかはメモの結果により既に求められている為、この部分の比較を簡略化することができます。

CodeSandbox上にを作りました。ボタンをクリックすると親階層の状態が更新される事により子コンポーネントも更新されようとしますが、浅い比較によりMemoFooではコンポーネントが更新されない事が確認できます。