generated at
Reactでのメモ化の方針






useMemo
計算に1msかかるならuseMemo





↓古いmrsekut
古いというのは、mrsekutの中の考えとして古いだけで、React側でなにか変化があったわけではない
ちょっと考えが変わっている
書き直すモチベが今はないので放置している
リンク先だけ参考にして、このページの内容はあまり参考にしないほうがいいかも


Reactのパフォーマンスにも関連する話
Reactの以下のようなメモ化処理を何も考えずにしまくったときに起きる弊害を考える



こういう思考になってしまう
defaultでmemoれば良いじゃん
じゃあ全部React.memoすればよくね?
useMemoとuseCallbackはデフォルトで良いじゃん?
これが、そうでもないんだよなー、という反論

他にもアンチパターンがある ref
useMemo, useCallbackに第二引数を書かない
depsにその場で生成したオブジェクトを入れる ref
冗長になっているだけ
適切でない値をdepsに入れているので意図通りの挙動にならない



結論
「メモ化した値との比較処理」v.s.「メモ化せずに新しく生成するなど」の対立構造になる
厳密に見るためには、いちいち検証が必要
そんなことはやってられないので勘と妥協でどうにかする
単純にdepsの数が増えるほど比較コストが上がる ref

実装の該当場所
useCallback ref


useMemo
値の計算コスト v.s. メモ化比較
その値を作る計算が複雑になるほどコストは上がる
ちょっとでもコストがありそうなら使っておけばいい


useCallback
再描画のコスト v.s. メモ化比較
「新しく関数インスタンスを生成」するところというよりも。
なので、子に参照を渡さないのであれば使う意味はない
逆に、子に渡すなら使っておけばいい
>関数インスタンスを作成するコストは先ほどの is関数の比較するコストよりおそらく低いでしょうref
個人的には直感に反するmrsekut
検証してみたい
例えば、コンポーネント生成時に一回作ったらそれを使えば良い状況でも子に渡さなかったら無意味になるの?
第2引数が useCallback(fn, []) となる状況のとき
特にコンポーネントがform等の場合は、人文字入力するごと(?)に、その関数が再生成されることになる
その中身は全く変わらないにもかかわらずだ


React.memoを使わないほうが良い場合ってどういう時?
第2引数を省略した場合、shallow equal比較なのでネストが深いコンポーネントを渡している場合は、意図せず再描画されなくなる
具体例を見たいmrsekut
頻繁に変わりうるpropsを複数受け取るコンポーネントの場合は比較コストのほうが大きくなる
つまり、比較関数がほぼ常にfalseを返すような状況
第二引数を省略しても、省略しなかったとしても
useCallbackを使わずに、親で定義されたmethodが渡ってきた場合も無意味なので、比較コストだけがかかる感じになる
無意味なのは、関数オブジェクトは生成するたびに異なるものになるから
ts
const sumFactory = () => { return (a, b) => a + b; } const sum1 = sumFactory(); const sum2 = sumFactory(); console.log(sum1 === sum2); // => false



バグの発生しやすさ
useMemoやuseCallbackを使うと、相対的にバグが出る可能性は上がる
もちろん何も考えずにdepsを書いている時の話
逆にあえてバグらそうと思ったらどうすればいい #??
Lintで防ぐ ref





関連
useStateの再描画はバッチ処理される


参考
計測して1ms以上かかるならuseMemoを使う
useCalback, useMemoについて
内部実装のコールドリーディングなど
setCount(count + 1) ではなく setCount(prev => prev + 1) と書こうという話