useMemoの役割、いつ使うべきかと注意点について

概要

useMemoの役割や使わない方が良い場合についてまとめようと思います

useMemoの役割

useMemoは計算結果のキャッシュを保持して高速化する目的で使用されます。

  const tasks = useMemo(
    () => filterTasks(term),
    [term]
  );

上記の例では初回レンダー時に計算結果がキャッシュされて、dependenciesに登録されたtermの値が変更されたら、再計算して計算した値をキャッシュします。

細かい説明はここで書ききらず公式にお任せします。

useMemoをいつ使うべきか

useMemoを使う上で、公式では使うケースは以下に限られると書かれているので引用します。
とりあえずuseMemoを使う、という運用は、重大な害はないがコードが読みにくくなるデメリットがあると公式で言及されています。

useMemo を利用した最適化が力を発揮するのは、以下のような、ほんの一部のケースに限られます。

  • useMemo で行う計算が著しく遅く、かつ、その依存値がほとんど変化しない場合。

  • 計算した値を、memo でラップされたコンポーネントの props に渡す場合。この場合は、値が変化していない場合には再レンダーをスキップしたいでしょう。メモ化することで、依存値が異なる場合にのみコンポーネントを再レンダーさせることができます。

  • その値が、後で何らかのフックの依存値として使用されるケース。例えば、別の useMemo の計算結果がその値に依存している場合や、useEffect がその値に依存している場合などです。

これらのケース以外では、計算を useMemo でラップすることにメリットはありません。

改めて公式を見てみると、キャッシュが効くからとりあえず使おう、という意識ではなく、適切な状況でしっかり使うことを意識するのが大事ですね。
また、計算コストが高いかどうかを見分ける方法 も解説されており、1ms 以上の場合はメモ化を検討しても良いと書かれています。

注意点について

Strict Modeの開発環境の場合、useMemoは二回呼び出されます https://ja.react.dev/reference/react/useMemo#my-calculation-runs-twice-on-every-re-render