setState的連鎖反應
這是一個React組件實現組件可交互所需的流程,render()輸出虛擬DOM,虛擬DOM轉爲DOM,再在DOM上註冊事件,事件觸發setState()修改數據,在每次調用setState方法時,React會自動執行render方法來更新虛擬DOM,如果組件已經被渲染,那麼還會更新DOM中去。這個過程,setState就像一個點燃引擎的火源,發動了React核心的調度層,然後直至渲染層的改變。
異步的setState
剛接觸React的同學,對React的setState的使用偶爾會有一些偏頗,出現一些意料之外的情況。例如:
onFunction=()=>{
this.setState({value: []});
// 此刻立馬取this.state做一些同步操作
console.log(this.state.value);
所以經常犯這個錯的同學需要謹記下面這幾點:
- setState是異步的,不會立即改變state的值。
- 多次setState調用生成的效果會合並。
- 第二個參數可以是一個回調函數。
- setState可以接受一個函數
爲什麼要異步呢?
每一次setState如果都引發一次組件更新,走完一圈生命週期,實在是有點粗糙和浪費,生命週期函數爲純函數性能應當還能夠接受,可是render函數內返回的虛擬DOM去做比較這個就比較費時間了。
直觀的感受是,React將多個setState產生的修改放在一個隊列裏,緩一緩,攢在一起,等待時機,覺得差不多了再引發一次更新過程。這樣,在每次更新過程中,會把積攢的setState結果合併,做一個merge的動作,節省render觸發的頻率。
這樣,對於開發者而言,可以在同步代碼中隨意多行調用setState函數而不用擔心重複setState重複render的問題。
然後,總是被大家誤用不理解的也是這一點,所以後來,setState方法的第二個參數慢慢被進入大家的視野了,作爲回調函數可以再次拿到新的this.state值。
再後來,一個setState函數的隱藏功能進入了大家的視野,那就是setState可以接受一個函數作爲參數。
this.setState(function (state, props) {
return {
value: state.value - 1
}
});