真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

React中setState的更新機(jī)制是什么

這篇文章主要介紹“React中setState的更新機(jī)制是什么”,在日常操作中,相信很多人在React中setState的更新機(jī)制是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”React中setState的更新機(jī)制是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司提供網(wǎng)站設(shè)計(jì)和自適應(yīng)建站服務(wù)。團(tuán)隊(duì)由有經(jīng)驗(yàn)的網(wǎng)頁(yè)設(shè)計(jì)師、程序員和市場(chǎng)專家組成,能夠提供從H5場(chǎng)景定制,網(wǎng)站制作,一元廣告,模板建站到微信小程序開(kāi)發(fā)等全方位服務(wù)。 以客戶為中心,致力于為客戶提供創(chuàng)新、高效的解決方案,幫助您打造成功的企業(yè)網(wǎng)站。

setState作為react中的重要部分,將對(duì)組件 state 的更改排入隊(duì)列,并通知 React 需要使用更新后的 state 重新渲染此組件及其子組件。

React中setState的更新機(jī)制是什么

stateReact中的重要概念。我們知道,React是通過(guò)狀態(tài)管理來(lái)實(shí)現(xiàn)對(duì)組件的管理。那么,React是如何控制組件的狀態(tài)的,又是如何利用狀態(tài)來(lái)管理組件的呢?【相關(guān)推薦:redis視頻教程】

我們都知道,React通過(guò)this.state來(lái)訪問(wèn)state,通過(guò)this.setState()方法更新state。當(dāng)this.setState()被調(diào)用的時(shí)候,React會(huì)重新調(diào)用render方法來(lái)重新渲染UI。

setState已經(jīng)是我們非常熟悉的一個(gè)API,然而你真的了解它嗎?下面我們將一起來(lái)解密setState的更新機(jī)制。

setState異步更新

大家剛開(kāi)始寫(xiě)React的時(shí)候,通常會(huì)寫(xiě)出 this.state.value = 1 這樣的代碼,這是完全錯(cuò)誤的寫(xiě)法。

注意:絕對(duì)不要直接修改 this.state,這不僅是一種低效的做法,而且很有可能會(huì)被之后的操作替換。

setState通過(guò)一個(gè)隊(duì)列機(jī)制實(shí)現(xiàn)state更新。當(dāng)執(zhí)行setState時(shí),會(huì)將需要更新的state合并后放入狀態(tài)對(duì)列,而不會(huì)立刻更新this.state,隊(duì)列機(jī)制可以高效地批量更新state。如果不通過(guò)setState而直接修改this.state的值,那么該state將不會(huì)被放入狀態(tài)隊(duì)列中,當(dāng)下次調(diào)用setState 并對(duì)狀態(tài)隊(duì)列進(jìn)行合并時(shí),將會(huì)忽略之前直接被修改的 state,而造成無(wú)法預(yù)知的錯(cuò)誤。

因此,應(yīng)該使用 setState 方法來(lái)更新 state,同時(shí) React 也正是利用狀態(tài)隊(duì)列機(jī)制實(shí)現(xiàn)了 setState的異步更新,避免頻繁地重復(fù)更新 state。相關(guān)代碼如下:

// 將新的state合并到狀態(tài)更新隊(duì)列中
var nextState = this._processPendingState(nextProps, nextContext);

// 根據(jù)更新隊(duì)列和 shouldComponentUpdate 的狀態(tài)來(lái)判斷是否需要更新組件
var shouldUpdate = this._pendingForceUpdte || !inst.shouldCompoonentUpdate || inst.shouldComponentUpdate(nextProps, nextState, nextContext0;

setState循環(huán)調(diào)用風(fēng)險(xiǎn)

當(dāng)調(diào)用setState時(shí),實(shí)際上會(huì)執(zhí)行 enqueueSetState 方法,并對(duì) partialState 以及 _pendingStateQueue 更新隊(duì)列進(jìn)行合并操作,最終操作 enqueueSetState 執(zhí)行 state 更新。

performUpdateIfNecessary 方法會(huì)獲取 _pendingElement、_pendingStateQueue、_pendingForceUpdate,并調(diào)用 receiveComponentupdateComponent 方法進(jìn)行組件更新。

如果在 shouldComponetUpdatecomponentWillUpdate 方法中調(diào)用 setState, 此時(shí) this._pendingStateQueue != null, 則 performUpateIfNecessary 方法就會(huì)調(diào)用 updateComponent 方法進(jìn)行組件更新,但 updateComponent 方法又會(huì)調(diào)用 shouldComponentUpdatecomponentWillUpdate 方法,因此造成循環(huán)調(diào)用,使得瀏覽器內(nèi)存占滿后崩潰。

React中setState的更新機(jī)制是什么

setState調(diào)用棧

既然 setState 最終是通過(guò) enqueueUpate 執(zhí)行 state 更新,那么 enqueueUpdate 到底是如何更新 state 的呢?

首先,看看下面這個(gè)問(wèn)題,你是否能夠正確回答呢?

import React, { Component } from 'react'

class Example extends Component {
  constructor() {
    super()
    this.state = {
      val: 0
    }
  }
  
  componentDidMount() {
    this.setState({val: this.state.val + 1})
    console.log(this.state.val) 
    
    this.setState({val: this.state.val + 1})
    console.log(this.state.val) 
    
    setTimeout(() => {
      this.setState({val: this.state.val + 1})
      console.log(this.state.val) 
      this.setState({val: this.state.val + 1})
      console.log(this.state.val) 
    },0)
  }
  
  render() {
    return null
  }
}

上述代碼中, 4 次 console.log 打印出來(lái)的 val 分別是:0、0、2、3。

假如結(jié)果與你心中的答案不完全相同,那么你是否想知道 enqueueUpdate 到底做了什么? 下圖是一個(gè)簡(jiǎn)化的 setState 調(diào)用棧,注意其中核心的狀態(tài)判斷。

React中setState的更新機(jī)制是什么

setState簡(jiǎn)化調(diào)用棧

解密setState

到底是怎么導(dǎo)致 setState 的各種不同表現(xiàn)的呢?

我們先要了解事務(wù)跟 setState 的不同表現(xiàn)有什么關(guān)系。首先,我們把4次 setState 簡(jiǎn)單歸類,前兩次屬于一類,因?yàn)樗麄冊(cè)谕淮握{(diào)用棧中執(zhí)行,setTimeout 中的兩次 setState 屬于另一類,因?yàn)樗麄円彩窃谕淮握{(diào)用棧中執(zhí)行。我們分析一下這兩類 setState 的調(diào)用棧。

componentDidMount 中直接調(diào)用的兩次 setState,其調(diào)用棧更加復(fù)雜;而setTimeout 中調(diào)用的兩次 setState,其調(diào)用棧則簡(jiǎn)單很多。下面我們重點(diǎn)看看第一類 setState 的調(diào)用棧,我們發(fā)現(xiàn)了 batchedUpdates 方法,原來(lái)早在 setState 調(diào)用前,已經(jīng)處于batchedUpdates執(zhí)行的事務(wù)中了。

batchedUpdates方法,又是誰(shuí)調(diào)用的呢?我們?cè)偻白匪菀粚?,原?lái)是 ReactMount.js 中的 _renderNewRootComponent方法。也就是說(shuō),整個(gè)將React組件渲染到DOM中的過(guò)程就處于一個(gè)大的事務(wù)中。

接下來(lái)的解釋就順理成章了,因?yàn)樵?code>componentDidMount中調(diào)用setState時(shí),batchingStrategyisBatchingUpdates 已經(jīng)被設(shè)為true,所以兩次setState的結(jié)果并沒(méi)有立即生效,而是被放到了dirtyComponents中。這也解釋了兩次打印 this.state.val 都是 0 的原因,因?yàn)樾碌?state 還沒(méi)有被應(yīng)用到組件中。

React中setState的更新機(jī)制是什么

componentDidMountsetState的調(diào)用棧

React中setState的更新機(jī)制是什么

setTimeoutsetState的調(diào)用棧

再反觀 setTimeout 中的兩次setState,因?yàn)闆](méi)有前置的 batchedUpdate 調(diào)用,所以 batchingStrategyisBatchingUpates 標(biāo)志位是false,也就導(dǎo)致了新的 state 馬上生效,沒(méi)有走到 dirtyComponents 分支。也就是說(shuō),setTimeout 中第一次執(zhí)行 setState 時(shí),this.state.val1, 而 setState 完成打印后打印時(shí) this.state.val 變成了2。第二次的 setState 同理。

前面介紹事務(wù)時(shí),也提到了其在 React 源碼中的多處應(yīng)用,像 initialize、perform、close、closeAll、motifyAll 等方法出現(xiàn)在調(diào)用棧中,都說(shuō)明當(dāng)前處于一個(gè)事務(wù)中。

既然事務(wù)這么有用,我們寫(xiě)應(yīng)用代碼時(shí)能使用它嗎?很可惜,答案是不能。盡管React不建議我們直接使用事務(wù),但在 React 15.0 之前的版本中還是為開(kāi)發(fā)者提供了 batchedUpdates 方法,它可以解決針對(duì)一開(kāi)始例子中setTimeout 里的兩次 setState 導(dǎo)致兩次 render 的情況:

import ReactDOM, { unstable_batchedUpates } from 'teact-dom'

unstable_batchedUpates(() => {
  this.setState(val: this.state.val + 1)
  this.setState(val: this.state.val + 1)
})

React 15.0 以及之后版本中,已經(jīng)徹底將 batchUpdates 這個(gè) API 移除了,因此不再建議開(kāi)發(fā)者使用它。

到此,關(guān)于“React中setState的更新機(jī)制是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!


網(wǎng)站標(biāo)題:React中setState的更新機(jī)制是什么
網(wǎng)頁(yè)網(wǎng)址:http://weahome.cn/article/pcjjdj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部