setState的"異步"小結

前言

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

1. 生命週期函數中

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

2.合成事件中

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

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

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是同步的,或者是帶引號的"異步"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章