[React] useCallback、useMemo、React.memoによるメモ化

メモ化(memoization

プログラムの高速化のための最適化技法の一種であり、サブルーチン呼び出しの結果を後で再利用するために保持し、そのサブルーチン(関数)の呼び出し毎の再計算を防ぐ手法

https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%A2%E5%8C%96

memorization(記憶、暗記)と混同しないこと

useCallback

const memoizedCallback = useCallback(
    () => {
        doSomething(a, b);
    },
    [a, b],
);

レンダリング間でコールバック関数を記憶しておくために使うフック。

  • 依存配列の要素が変化しない限り、同じコールバック参照が維持される。
  • このとき、useCallbackでメモ化したコールバック関数を、React.memoでメモ化したコンポーネントにpropsとして渡すと、(propsが同一と判定されて)コンポーネントの再レンダリングを抑制できる。

useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

レンダリング間でを記憶しておくために使うフック。

  • 依存配列の要素が変化しない限り、同じ値が維持される。
  • このとき、useMemoでメモ化した値を、React.memoでメモ化したコンポーネントにpropsとして渡すと、(propsが同一と判定されて)コンポーネントの再レンダリングを抑制できる。

以下の2つは等価である。

useCallback(fn, deps)
useMemo(() => fn, deps)

React.memo

const MyComponent = React.memo(function MyComponent(props) {
    /* render using props */
});

レンダリング間でReactコンポーネントを記憶しておくために使う高階コンポーネント (higher-order component; HOC)

  • propsが変更されていない場合、レンダリングをスキップし、直前のレンダリング結果を返す。
  • ただし、コンポーネント内でuseState、useReducer、useContextフックを使っている場合、stateやコンテキストの変化に応じた再レンダリングは発生する。

https://ja.reactjs.org/docs/hooks-reference.html