溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

setState的用法有哪些

發(fā)布時(shí)間:2021-10-18 09:28:19 來源:億速云 閱讀:153 作者:柒染 欄目:web開發(fā)

setState的用法有哪些,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡單易行的方法。

setState是同步還是異步?

首先,這個(gè)問題的拋出,我會(huì)想為什么要拋出這個(gè)問題呢?如果說,你需要依賴狀態(tài)更新后的值時(shí),那么首先如何做呢?

  • 對(duì)于Class Component而言,我們可以在componentDidMount或者是componentDidUpdate階段來執(zhí)行。

  • 對(duì)于Function Component而言,我們可以在useEffect的回調(diào)函數(shù)中執(zhí)行。

首先,我們先給出結(jié)論,在React中不同的模式它的情況是不一樣的,主要拿兩種模式來說。

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. legacy模式

  3. concurrent模式

legacy 模式

這是當(dāng)前 React app 使用的方式??

ReactDOM.render(<App />, rootNode)

當(dāng)前沒有計(jì)劃刪除本模式,但是這個(gè)模式可能不支持這些新功能。

回到我們上述的問題,setState是同步的還是異步的?

  • 當(dāng)在legacy模式下,命中batchedUpdates時(shí),setState是異步的。

  • 當(dāng)在legacy模式下,沒命中batchedUpdates時(shí),setState是同步的。

既然聊到了這里,我們來說一說batchedUpdates函數(shù)的作用。

那么它是干嘛的呢?如果你在處理邏輯函數(shù)中多次調(diào)用this.setState時(shí),它是如何更新狀態(tài)的呢?

this.setState({   value: this.state.value + 1 }) this.setState({   value: this.state.value + 1 }) this.setState({   value: this.state.value + 1 })

那React實(shí)現(xiàn)了這個(gè)批量更新的操作,將多次的setState合并為一次更新,那么它是如何實(shí)現(xiàn)的呢?batchedUpdates函數(shù)就登場了。

function batchedUpdates$1(fn, a) {     var prevExecutionContext = executionContext;     executionContext |= BatchedContext;      try {       return fn(a);     } finally {       executionContext = prevExecutionContext;        if (executionContext === NoContext) {         // Flush the immediate callbacks that were scheduled during this batch         resetRenderTimer();         flushSyncCallbackQueue(); // 同步的更新       }     }   }

這個(gè)函數(shù)會(huì)傳遞一個(gè)fn,當(dāng)執(zhí)行fn之前,會(huì)在executionContext變量上附加一個(gè)BatchedContext,當(dāng)fn執(zhí)行完畢后,executionContext就會(huì)把之前的BatchedContext標(biāo)記給去除掉。

  • 這樣子一來,當(dāng)executionContext帶上了BatchedContext標(biāo)記的話,react內(nèi)部就會(huì)去做判斷,帶上了這個(gè)標(biāo)記,這次的更新就是批處理,那么此次更新就是異步的。

那么,我們是不是能夠假設(shè)一下,如果在執(zhí)行完fn函數(shù)后,再去更新狀態(tài)的話,是不是就能完成同步的更新呢?

setTimeout函數(shù),我們可以把setState放在定時(shí)器中,這樣子一來的話,當(dāng)fn函數(shù)執(zhí)行完時(shí),BatchedContext標(biāo)記也去掉了,然后等到  setTimeout 的回調(diào)函數(shù)等到空閑被執(zhí)行的時(shí)候,才會(huì)執(zhí)行 setState。

setTimeout(() => {     this.setState({ value: this.state.value + 1})   }, 0)

這也就是當(dāng)executionContext ===  NoContext,也就是會(huì)執(zhí)行flushSyncCallbackQueue函數(shù),完成此次的同步更新。

當(dāng)然了,在concurrent 模式下,又是有所不同的。

這個(gè)時(shí)候,我們得談一談scheduleUpdateOnFiber函數(shù)。

我們都知道任務(wù)調(diào)度的起點(diǎn)是 scheduleUpdateOnFiber  方法,React.render、setState、forceUpdate、React Hooks 的dispatchAction 都會(huì)經(jīng)過  scheduleUpdateOnFiber。

function scheduleUpdateOnFiber(fiber, lane, eventTime) {     // ...     if (root === workInProgressRoot) {       // ......      } // TO an argument to that function and this one.     if (lane === SyncLane) {  // 同步任務(wù)       if ( // 檢查當(dāng)前是不是在unbatchedUpdates(非批量更新),(初次渲染的ReactDOM.render就是unbatchedUpdates)       (executionContext & LegacyUnbatchedContext) !== NoContext && // Check if we're not already rendering       (executionContext & (RenderContext | CommitContext)) === NoContext) {         // Register pending interactions on the root to avoid losing traced interaction data.         schedulePendingInteractions(root, lane);          performSyncWorkOnRoot(root);       } else {         ensureRootIsScheduled(root, eventTime);         schedulePendingInteractions(root, lane);         if (executionContext === NoContext) {           resetRenderTimer();           flushSyncCallbackQueue();         }       }     } else { // 異步任務(wù)       // concurrent模式下是跳過了 flushSyncCallbackQueue 同步更新       // ....     }    }

scheduleUpdateOnFiber函數(shù)通過lane ===  SyncLane來判斷是同步任務(wù)還是異步任務(wù),我們通過ReactDom.render()方式創(chuàng)建的React  app是會(huì)進(jìn)入這個(gè)判斷的,而concurrent模式下,則不同,那么它是如何創(chuàng)建的呢??

concurrent 模式

你可以理解成,這個(gè)暫時(shí)還是實(shí)驗(yàn)階段,當(dāng)未來穩(wěn)定后,將會(huì)作為React開發(fā)的默認(rèn)開發(fā)模式,它是如何創(chuàng)建一個(gè)React App應(yīng)用的呢??

ReactDOM.createRoot(rootNode).render(<App />)

這個(gè)模式開啟了所有的新功能。

concurrent模式下狀態(tài)的更新都是異步的。

關(guān)于React的concurrent 模式解讀,有興趣可以看看官方文檔。

到這里的話,似乎我們對(duì)React中setState是同步的還是異步的就有所了解了。

  • 哪些會(huì)命中batchUpdate機(jī)制

  • 生命周期(和它調(diào)用函數(shù))

  • React中注冊(cè)的事件

  • React可以'管理入口'

關(guān)于setState的用法有哪些問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI