$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

ReactのuseEffect/useLayoutEffectやレンダリングの実行順について調べた

useEffect/useLayoutEffect周りで絶賛ハマり中で、また React17におけるuseEffectの破壊的変更を理解する | Zenn の記事が面白かったので、自分の手元で動かしてみて理解を深めてみた。調査したことを自分用のメモとして取っておく。React 17でuseEffect周りで破壊的な変更が入るということなので、Reactのバージョンは17.0.0-rc.1で試した。

気になっていたこと

  • 親子のコンポーネントでuseEffectがどの順で実行されているのか
  • useLayoutEffectが途中にあるとどのような挙動をするか
  • useEffect/useLayoutEffectとレンダリングやDOMへの反映の実行順序

調査メモ

shibayu36/typescript-playground/react-playground あたりで試した。react-playground ディレクトリ以下でyarn installしてyarn startしたら試せる。

以下2つのエンドポイントを実装し、行き来しながらどのようなログが出るか見た。

/ -> /effect-order へアクセスした時は以下のようなログが出る。この時、LayoutEffect useLayoutEffect では同期的に2秒待ちを入れていたので、実際に画面に表示されるのは2秒後となった。Child useEffectは2秒待ちを入れていたが、画面表示には影響せず、その代わり後続のuseEffectは遅延された。

EffectOrder rendering
Effect rendering
LayoutEffect rendering
Child rendering
Home ref null
Child ref <div>​Child Component​</div>​
LayoutEffect ref <div>​…​</div>​
LayoutEffect useLayoutEffect
Effect ref <div>​…​</div>​
EffectOrder ref <div>​…​</div>​
Child useEffect
Effect useEffect
EffectOrder useEffect

/effect-order -> / のときは以下のようなログが出る。こちらもuseLayoutEffectのcleanupに2秒待ちを入れていたのでそれが実行されるまでDOMへの反映も遅延された。

Home rendering
EffectOrder ref null
Effect ref null
LayoutEffect useLayoutEffect cleanup
LayoutEffect ref null
Child ref null
Home ref <header class=​"App-header">​…​</header>​
EffectOrder useEffect cleanup
Effect useEffect cleanup
Child useEffect cleanup

この実行から分かったことは

  • Virtual DOMの構築はたぶん「... rendering」というログのところで実行されていそうなので、useEffect/useLayoutEffect関係なく作られてそう
  • 実際のDOM構築はたぶん「... ref」というログのところで実行されていそうなので、useLayoutEffectはこのタイミングで実行される。実際のDOM構築が全て終わらないと画面表示出来ないので、useLayoutEffectで重い処理をするとユーザーへの描画タイミングが遅れる
  • useEffectはDOM構築が終了した後に実行されるので表示には影響しない。マウント時は子から親の順で実行され、アンマウント時は親から子の順で実行される。途中で重い処理が行われていると後続のuseEffectは遅延する。

フェーズとしては、Virtual DOM構築フェーズ、実際のDOM構築 & useLayoutEffect実行フェーズ、useEffect実行フェーズがある感じか?

まとめ

ReactのuseEffect/useLayoutEffectやレンダリングの実行順について調べたので自分用のメモを残してみた。Reactのドキュメントに書いてあるような内容を再確認しただけにはなったが、自分の手を動かしたためか、もっと実感を持って理解できたような気がする。

参考文献