useEffect和useLayoutEffect執行時機


流程

  1. react在diff之后,會進入commit階段,將新生成的虛擬DOM發生的變化映射到真實DOM上
  2. 在commit的前期,會調度一些生命周期方法,對於類組件來說,會觸發getSnapshotBeforeUpdate。對於函數組件來說,會調度useEffect。
  3. 但是並不是立即執行,在此階段,會把useEffect入列到react維護的調度隊列中,給一個普通的優先級,異步執行。
  4. 之后,在將新生成的虛擬DOM發生的變化映射到真實DOM上的過程中,會通過commitWalk根據不同的fiberNode進行DOM修改。
  5. 當commitWalk遇到類組件時,不會進行任何操作,因為沒有真實的dom節點,直接return,處理下一個節點
  6. 但對於有了hooks的函數組件來說,會同步調用上一次渲染時useLayoutEffect函數的destroy方法
  7. 注意節點在commitWalk后,變化已經被映射到真實的DOM上了
  8. 但是由於JS線程和渲染線程是互斥的,真實的DOM雖然已經改變了,瀏覽器卻沒有立刻渲染到屏幕上
  9. 此時會同步執行對應的生命周期方法,如componentDidmount、componentDidUpdate以及useLayoutEffect的create方法。此時如果對DOM進行了操作,會一起處理
  10. 在react中,commit不會被打斷,直至所有節點都commit結束,react更新完成,JS才停止執行
  11. 瀏覽器此時才會進入渲染線程,將發生變化的DOM渲染到屏幕上,因此react只用了一次回流、重繪的代價,將所有需要更新的DOM節點更新了
  12. 瀏覽器渲染完成后,react開始之前之前提到的調度隊列,才開始執行useEffct產生的函數

一些結論

  1. useEffect的create函數,調用時機和位置都與componentDidMount,componentDidUpdate 一致,且都是被 React 同步調用,都會阻塞瀏覽器渲染。

  2. 將對DOM的操作放在useLayoutEffect中,性能更好


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM