react的setState使用詳解

react修改狀態(tài)是不能直接修改的,需要使用setState來(lái)進(jìn)行狀態(tài)的修改,但是setState的使用會(huì)存在一些問(wèn)題。覺(jué)得有必要在此做一下總結(jié)。。。。

setState()不是立刻更新組件。其可能是批處理或推遲更新。這使得在調(diào)用setState()后立刻讀取this.state的一個(gè)潛在陷阱。

就像這樣:

incrementCount() {
  this.setState({count: this.state.count + 1});
}
handleSomething() {
  this.incrementCount();
  this.incrementCount();
  this.incrementCount();
}
調(diào)用了3次incrementCount方法, 期望this.state.count的值是3, 但最后卻是1

本質(zhì)上setState修改state的值是通過(guò)淺合并把新的值合并到state的對(duì)象上,如果多次修改,react會(huì)進(jìn)行批次處理

類(lèi)似于:

Object.assign(
  previousState,
  {count: state.count + 1},
  {count: state.count + 1},
  {count: state.count + 1},
)
之后的調(diào)用在同一周期中將會(huì)重寫(xiě)之前調(diào)用的值,因此數(shù)量?jī)H會(huì)被加一。若之后的狀態(tài)依賴于之前的狀態(tài),

解決這個(gè)問(wèn)題的方式:

componentDidUpdate或一個(gè)setState回調(diào)(setState(updater, callback))

  1. 當(dāng)中的每個(gè)方法都會(huì)保證在更新被應(yīng)用之后觸發(fā)
  2. updater函數(shù)接收到的prevState 和 props保證都是最新的
incrementCount() {
  this.setState((state) => {
    return {count: state.count + 1}
  });
}
handleSomething() {
  this.incrementCount();
  this.incrementCount();
  this.incrementCount();
}

setState什么時(shí)候會(huì)異步更新

setState的執(zhí)行流程:

this.setState(newState)
==>
newState存入pending隊(duì)列
==>
判斷是否處于batch update
==>
如果是的話就保存組件月dirtyComponents中,
如果不是的話就遍歷所有的dirtyComponents,調(diào)用updateComponent,更新pending state or props

在 React 的 setState 函數(shù)實(shí)現(xiàn)中,會(huì)根據(jù)一個(gè)變量 isBatchingUpdates 判斷是直接更新 this.state 還是放到隊(duì)列中回頭再說(shuō),
而 isBatchingUpdates 默認(rèn)是 false,也就表示 setState 會(huì)同步更新 this.state,
但是,有一個(gè)函數(shù) batchedUpdates,這個(gè)函數(shù)會(huì)把 isBatchingUpdates 修改為 true,
而當(dāng) React 在調(diào)用事件處理函數(shù)之前就會(huì)調(diào)用這個(gè) batchedUpdates,造成的后果,就是由 React 控制的事件處理過(guò)程 setState 不會(huì)同步更新 this.state。

  • setState會(huì)導(dǎo)致re-rederning, 而re-rederning的代價(jià)是昂貴的, 所以他們會(huì)盡可能的把多次操作合并成一次提交。
  • 因?yàn)楫?dāng)傳入的是一個(gè)函數(shù)時(shí),state讀取的是pending隊(duì)列中state的值

setState什么時(shí)候會(huì)異步更新, 什么時(shí)候會(huì)同步更新

React是根據(jù)isBatchingUpdates來(lái)合并更新的, 那么當(dāng)調(diào)用setState的方法或者函數(shù)不是由React控制的話, setState自然就是同步更新了。

  1. 如componentDidMount等生命周期以及React的事件即為異步更新,這里不顯示具體代碼。
  2. 如自定義的瀏覽器事件,setTimeout,setInterval等脫離React控制的方法, 即為同步更新
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容