淺入深出setState(上篇)

Part one - setState點燃引擎

setState點燃引擎

這是一個React組件實現組件可交互所需的流程,render()輸出虛擬DOM,虛擬DOM轉爲DOM,再在DOM上註冊事件,事件觸發setState()修改數據,在每次調用setState方法時,React會自動執行render方法來更新虛擬DOM,若是組件已經被渲染,那麼還會更新到DOM中去。
這個過程,setState就像一個點燃引擎的打火石,發動了React核心的調度層,而後直至渲染層的改變。react

Part two - setState是異步的

剛接觸React的同窗,對React的setState的使用偶爾會有一些偏頗,出現一些意料以外的狀況。
好比:git

onClickForReset=()=>{
    this.setState({value: []});
    // 此刻立馬取this.state作一些同步操做
    console.log(this.state.value);
}

或者是github

increateCount(){
    this.setState({count: this.state.count + 1});
    this.setState({count: this.state.count + 1});
    this.setState({count: this.state.count + 1});
}

咱們能夠看一個如今的例子:
https://codesandbox.io/s/qqy9n5o2m9性能優化

https://codesandbox.io/s/qqy9n5o2m9

setState比較熟練的同窗能夠跳過這一段代碼,可是有些剛學會使用React的同窗常常會犯這個錯誤,一開始我只能粗暴地說:異步

  1. setState是異步的,不會當即改變state的值。
  2. 屢次setState調用生成的效果會合並。
  3. 第二個參數能夠是一個回調函數。
  4. setState能夠接受一個函數(例子改動)

後來我逐漸也在想下面這兩個問題,如今這篇文章試圖儘可能弄清的兩件事:函數

  1. 爲何要把setState設計成異步的,原因是什麼,解決了什麼問題,有什麼好處?
  2. 如何實現異步的setState,總體原理是怎樣的,有沒有什麼特殊的騷操做?

咱們能夠本身也想想,下面留給你們一片空白區。😝性能

<div style="background:#fff;width:100%;height:500px;margin-bottom:30px;"></div>優化

好,咱們帶着這兩個問題和本身的猜測,試圖一探究竟。this

Part three - 爲何要異步

簡單的來講:在批量屢次的更新中,延緩到最後合併渲染是有好處的。spa

萬劍歸宗

  1. 保證內部的一致性:首先,我想咱們都贊成推遲並批量處理重渲染是有益並且對性能優化很重要的,不管 setState() 是同步的仍是異步的。那麼就算讓 state 同步更新,props 也不行,由於當父組件重渲染(re-render )了你才知道 props。
  2. 在批量屢次的更新中,延緩到最後合併渲染是有好處的。這一點,和咱們熟知的防抖動函數的出發點相似,咱們廣泛認爲在許多狀況下在同一時間段,頻繁setState觸發渲染,連續同步效率很低,對性能有極大損耗。

咱們來看下setState引起組件的更新過程就知道了:

setState引起組件的更新過程

每一次setState若是都引起一次組件更新,走完一圈生命週期,實在是有點粗糙和浪費,生命週期函數爲純函數性能應當還可以接受,但是render函數內返回的虛擬DOM去作比較這個就比較費時間了。

直觀的感覺是,React將多個setState產生的修改放在一個隊列裏,緩一緩,攢在一塊兒,等待時機,以爲差很少了再引起一次更新過程。這樣,在每次更新過程當中,會把積攢的setState結果合併,作一個merge的動做,節省render觸發的頻率。
這樣,對於開發者而言,能夠在同步代碼中隨意多行調用setState函數而不用擔憂重複setState重複render的問題。

而後,老是被你們誤用不理解的也是這一點,因此後來,setState方法的第二個參數慢慢被進入你們的視野了,做爲回調函數能夠再次拿到新的this.state值。

再後來,一個setState函數的隱藏功能進入了你們的視野,那就是,setState能夠接受一個函數做爲參數。

更多: https://github.com/facebook/react/issues/11527#issuecomment-360199710

Part four - 怎麼實現異步

在此以前,咱們來看一個例子…可能會顛覆你對setState的認識

咱們能夠直接打開在線案例:https://codesandbox.io/s/vq1nqkvyw5

setState真的是異步嗎

提問:實際運行結果是怎麼樣的?好吧如今下

Part five - 彩蛋:setState真的是異步嗎?

咱們上面一個例子告訴咱們:

No! 多是同步 超出React生命週期和React代理事件以外都是同步

預知後事如何,請看下半篇。

相關文章
相關標籤/搜索