setState的"異步"小結

前言

關於setState的異步,隨便一搜就是一堆文章,從各類現象到海量源碼,長篇鉅製洋洋灑灑,像我這樣的新手看得雲裏霧裏,暈頭轉向。但這個問題又無比簡單,僅需理解兩點淺顯的道理,便能撥雲見日:1.同步代碼不可能異步;2.若是"異步"了,必定是執行順序發生了改變。react

1. 生命週期函數中

componentDidMount: 該方法執行完畢後才更新,state在更新時(render)再設置爲新的值。setState後續的代碼在生命週期函數中執行,此時state還未變動,所以表現出"異步"特性。異步

2.合成事件中

同理,setState在事件中同步執行完畢,react準備更新(will),state在更新時(render)再設置爲新的值。setState後續的代碼在觸發事件時執行,順序在state變動以前。函數

注:state的合併,只能將同步的setState合併掉,兩次事件的變動沒法合併,任你點擊得再快component

3.異步方法及原生事件

react監控的只有生命週期函數和合成事件,而非setState,在這兩個方法執行前會先設置isBatchingUpdates爲true,致使state等更新完畢後再改變,所以其餘狀況下,batchedUpdates爲false,setState同步更新。一樣,state也是在更新時設爲新的值,可是setState後續的代碼也是在更新完成以後執行,所以表現出同步特性。生命週期

注:同理,Promise的構造函數內的setState,由於構造函數的同步性,當其處於1和2的狀況下時,也會呈現出"異步"事件

4.結論

  • setState不是變動state的方法,只是發送了變動的請求
  • 不管是生命週期函數仍是合成事件函數,它們都會被放入react的事務中,而事務的前置鉤子內會修改isBatchingUpdates爲true
  • 因isBatchingUpdates爲true,setState會走批量更新模式,合併一樣的state,並不即時修改state,從而使後續的同步代碼在state變動前就執行了,表現出"異步"的特性
  • react沒有監控異步方法和原生事件,所以,即便它們聲明的時候處在生命週期函數或者合成事件中,它們執行的時候,isBatchingUpdates一定已經被事務的後置鉤子設爲false了,所以表現出同步的特性
  • 同步時,state的改變和後續代碼的執行,都是在did update後,"異步"時,先即便執行了後續的代碼,然後在did update以後執行了state的變動
  • 最後的總結就是,setState是同步的,或者是帶引號的"異步"
相關文章
相關標籤/搜索