tmegos blog

Web developer

Reactの再レンダリングをWhy Did You RenderとReact Profilerを使って調べる

Reactでできたアプリケーションのパフォーマンスチューニングのために、再レンダリングを調査し、改善したときのメモです

方針

  1. Why Did You Renderを使って、propsやstateが同じはずなのに再レンダリングが発生しているところを見つける
  2. 1で見つかった再レンダリングについて、それぞれの原因に応じた修正を行う
  3. Why Did You Renderがログを出さなく(またはログが少なく)なるまで1と2を繰り返す
  4. React Profilerを使って、再レンダリングが発生しているところを見つける
  5. 4で見つかった再レンダリングについて、componentの分割やMemo化を試みる

Why Did You Renderでサンプルとして使われているアプリケーションについて見ていきます

Why Did You Render Sandbox - CodeSandbox

1. Why Did You Renderを使って、propsやstateが同じはずなのに再レンダリングが発生しているところを見つける

レンダリングを調査するため、Why Did You Renderを導入します

github.com

Why Did You Renderを導入すると、回避可能な再レンダリングが発生した場合、consoleにログを出力してくれます

以下の図のように、

がconsoleにずらずらと表示されます

f:id:tmegos:20210411011608p:plain:w500
Why Did You Renderのログ

2. 1で見つかった再レンダリングについて、それぞれの原因に応じた修正を行う

Why Did You Renderの素晴らしい点は、再レンダリングが発生していることを知らせてくれるだけではなく、その原因や解決方法までもを教えてくれるところです

原因に応じた適切な解決方法で修正をしていきます

3. Why Did You Renderがログを出さなく(またはログが少なく)なるまで1と2を繰り返す

Why Did You Renderは、回避可能な再レンダリングを警告してくれるライブラリです
本当にpropsやstateが変わっている場合にはログは出力されません

Why Did You Renderを有効にしていてもconsoleがきれいな状態であれば、そのReactアプリケーションは健全な状態であるのだと思います

4. React Profilerを使って、再レンダリングが発生しているところを見つける

Why Did You Renderがログを出さなくなってもまだ重い、関係ないところも再レンダリングされていそう、という状態になったらReact Profilerの出番です

React Developer Toolsが入っていれば、開発者ツールにComponentsやProfilerタブが追加されています

chrome.google.com

Profilerタブで、「Start profiling」→「Stop profiling」をすると、プロファイリングした内容が確認できます

ここでは、Why did this render?の内容を確認します

f:id:tmegos:20210411013449p:plain:w500
propsが変わった

f:id:tmegos:20210411013513p:plain:w500
hooks(ここではstate)が変わった

ここで問題になるのが、hooksの変更です
Profilerを見ると、「Hooks changed」としか書かれておらず、どのhooksが変わって再レンダリングが起きたのかが判断できません

こちらの解決策は、Reactのissueコメントにありました

github.com

このコメントの通り、

  1. 現在のcomponentのhooksの状態をコピー
  2. アプリケーションを操作して、再レンダリングを発生させる
  3. 再びhooksの状態をコピー
  4. difftoolを使って差分を確認する

という操作をするとhooksの変更を調査することができます

f:id:tmegos:20210411015012p:plain:w500
stateが変化しているのがわかる

5. 4で見つかった再レンダリングについて、componentの分割やMemo化を試みる

原因がわかったので、再レンダリングを抑制する対応を行います

メモ化する前に、以下の記事を参考にするのもよさそうです

overreacted.io