Open4

react.dev の useMemo の メモ

ナガナガ

useMemoって何なの?

  • レンダー間で計算結果をキャッシュするためのフック
  • めっちゃ重い処理がある場合に使う
  • 基本的に使わなくても良い
  • よく分からんけど使っておけという認識であれば使わないほうが良い
  • アプリケーションの動作が重いなと感じるのであれば使うと良い
  • ごっついインタラクション(図形のアニメーションとか)がある場合は使うと良いかもしれない。

コードサンプル

import { useMemo } from 'react';

function TodoList({ todos, tab }) {
  // ここから
  const visibleTodos = useMemo(
    () => filterTodos(todos, tab),
    [todos, tab]
  ); 
  // ここまで
  // 以下略
}

引数

第一引数: calculateValue

前述のサンプルコードの下記部分が calculateValue といって、キャッシュしたい値を計算する関数。
純関数[1]である必要がある。
Reactが初回描画時にこの関数を呼び出す。
2回目以降は、後述する第二引数の dependencies が直前の描画から変化していなければ同じ値を返す。

() => filterTodos(todos, tab),

第二引数: dependencies

配列となっている下記部分が dependencies といって、 calculateValue のコード内で利用されているすべてのリアクティブ値[2]の配列を書く。
配列の長さは一定である必要がある。

[todos, tab]

返り値

初回描画時は依存配列(dependencies)無しで calculateValue を呼び出した結果が返り値となる。
2回目以降は依存配列が変化してなければ、以前の描画で保存された値を返す。
変化していたらもう一度 calculateValue を呼び出して、結果を返す。

脚注
  1. 純関数とは、引数が同じなら常に同じ返り値となり、副作用(関数外に影響)が発生しない関数を言う。 ↩︎

  2. リアクティブ値とは props または state 、コンポーネント本体で宣言されている全ての変数と関数のことを指す ↩︎

ナガナガ

そもそもメモ化って何よ?

呼び出した関数の結果をオブジェクトに保存(メモ)しておき、次回以降その関数を呼び出すときは保存しておいた値を利用する(不要な再計算を防ぐ)みたいな、プログラムの高速化に使われる技法。

Ref

https://ja.wikipedia.org/wiki/メモ化

ナガナガ

計算コストが高いかどうかを調べる

対象の関数を console.timeconsole.timeEnd で挟んで、実行にかかった時間を計測する。

console.time('filter array');
const visibleTodos = filterTodos(todos, tab);
console.timeEnd('filter array');

上記のような計測方法の結果が 1ms 以上になった場合、メモ化の効果が期待できる。

その他補足

  • useMemo は初回描画時は高速化しない。
    • 一度実行したものをメモ化しておくわけだから当然っちゃあ当然
  • 正確にパフォーマンスを計測するにはアプリを本番環境用にビルドする必要がある。できればユーザが持っているようなデバイスで動作検証するのが望ましい。