🥦
React.memoの内部ソースコードを読んでみました(本当に使うべきかを見極め)
React.memoの公式説明
公式の説明は以下ですね
ソースコードにReact.memoが効くための判断条件
判断条件
以下の二つの条件を満たしたら、React.memoで囲んだComponentを走りません
- 渡されたpropsとメモしているpropsとのshallow equalはtrueになっています。
これは公式の説明の以下の分に当てはまります
- Componentの中にはContextの変化がないこと
これは公式の説明の以下の分に当てはまります。
判断結果
1. 効果がある場合
1&2を満たしたら、以下の処理に入ります
つまり、React.memoで囲んだComponentに対して、子FiberNodeの更新がないことと想定され、
前のレンダリング段階の子FiberNodeをそのまま使います。
もちろん、React.memoで囲んだComponentは関数として走りません。(子FiberNodeの遺伝子React.Elementを作り出すために、関数を実行するわけです)
2. 効果がない場合
1&2を満たしなかったら、以下の処理に入ります
つまり、React.memoで囲んだComponentを実行して、子FiberNodeの新しいReact.Elementを生成して、現在のFiberNodeの子FiberNodeのpendingPropsを更新します。
React.memoを使うメリットとデメリット
メリット
- 頭を考えずに、Reactレンダリング時にReact.memoで囲んだ関数実行を最大限に抑えられます。
デメリット
- React.memoに対するひとつFiberNodeを増えています。(メモリのコスト)
- propsに対するshallowEqual処理(時間コスト)
- contextの変化があるかどうかの判断(時間コスト、なかにはwhile分があります)
使うかどうかの個人意見
ネット上ではReact.memoを使うかどうかの意見はあちこちにありますが、まよいますね。
もし囲んでいるComponentにはuseState,useReducer,useContext,useSelector(redux)
たくさんあって、そして、頻繁によばれるなら、使う意味はあまりないと思います。
なぜかというと、いくらuseMemoとuseCallbackをつかって、propsをメモして、第1条件を満たしても、第2条件はuseStateなどの更新によって、満たされてないなら、結局React.memoが囲んだComponentが走ります。
そうなると、無駄な時間コストとメモリのコストになります。
説明動画
Discussion