理解setState的關(guān)鍵
- setState不會立刻改變React組件中state的值嚎花;
- setState通過引發(fā)一次組件的更新過程來引發(fā)重新繪制怕享;
- 多次setState函數(shù)調(diào)用產(chǎn)生的效果會合并。
這幾個關(guān)鍵點其實是相互關(guān)聯(lián)的,一個一個說吧狈定。
需要用一個函數(shù)去更改狀態(tài)止状,這個函數(shù)就是setState,當(dāng)setState被調(diào)用時阳仔,能驅(qū)動組件的更新過程忧陪,引發(fā)componentDidUpdate、render等一系列函數(shù)的調(diào)用
調(diào)用this.setState時近范,并沒有立即更改this.state嘶摊,所以this.setState只是在反復(fù)設(shè)置同一個值而已
setState調(diào)用引起的React的更新生命周期函數(shù)4個函數(shù)(比修改prop引發(fā)的生命周期少一個componentWillReceiveProps函數(shù)),這4個函數(shù)依次被調(diào)用评矩。
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
當(dāng)shouldComponentUpdate函數(shù)被調(diào)用的時候叶堆,this.state沒有得到更新。
當(dāng)componentWillUpdate函數(shù)被調(diào)用的時候斥杜,this.state依然沒有得到更新虱颗。
直到render函數(shù)被調(diào)用的時候,this.state才得到更新蔗喂。
連續(xù)調(diào)用了兩次this.setState忘渔,但是只會引發(fā)一次更新生命周期,不是兩次缰儿,因為React會將多個this.setState產(chǎn)生的修改放在一個隊列里畦粮,緩一緩,攢在一起乖阵,覺得差不多了再引發(fā)一次更新過程宣赔。
在每次更新過程中,會把積攢的setState結(jié)果合并瞪浸,做一個merge的動作儒将,所以上面的代碼相當(dāng)于這樣。
function increment(state, props) {
return {count: state.count + 1};
}
function incrementMultiple() {
this.setState(increment);
this.setState(increment);
this.setState(increment);
}
對于多次調(diào)用函數(shù)式setState的情況对蒲,React會保證調(diào)用每次increment時钩蚊,state都已經(jīng)合并了之前的狀態(tài)修改結(jié)果
簡單說贡翘,加入當(dāng)前this.state.count的值是0,第一次調(diào)用this.setState(increment)两疚,傳給increment的state參數(shù)是0床估,第二調(diào)用時,state參數(shù)是1诱渤,第三次調(diào)用是丐巫,參數(shù)是2,最終incrementMultiple的效果勺美,真的就是讓this.state.count變成了3递胧,這個函數(shù)incrementMultiple終于實至名歸。
值得一提的是赡茸,在increment函數(shù)被調(diào)用時缎脾,this.state并沒有被改變,依然占卧,要等到render函數(shù)被重新執(zhí)行時(或者shouldComponentUpdate函數(shù)返回false之后)才被改變
傳統(tǒng)式setState的存在遗菠,會把函數(shù)式setState拖下水啊华蜒!只要有一個傳統(tǒng)式的setState調(diào)用辙纬,就把其他函數(shù)式setState調(diào)用給害了