日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
聊聊setState的用法,你會幾個?

本文轉(zhuǎn)載自微信公眾號「前端UpUp」,作者前端UpUp。轉(zhuǎn)載本文請聯(lián)系前端UpUp公眾號。

目前成都創(chuàng)新互聯(lián)公司已為成百上千家的企業(yè)提供了網(wǎng)站建設、域名、網(wǎng)站空間、網(wǎng)站托管運營、企業(yè)網(wǎng)站設計、營口網(wǎng)站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

setState是同步還是異步?

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

  • 對于Class Component而言,我們可以在componentDidMount或者是componentDidUpdate階段來執(zhí)行。
  • 對于Function Component而言,我們可以在useEffect的回調(diào)函數(shù)中執(zhí)行。

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

  1. legacy模式
  2. concurrent模式

legacy 模式

這是當前 React app 使用的方式??

 
 
 
  1. ReactDOM.render(, rootNode)

當前沒有計劃刪除本模式,但是這個模式可能不支持這些新功能。

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

  • 當在legacy模式下,命中batchedUpdates時,setState是異步的。
  • 當在legacy模式下,沒命中batchedUpdates時,setState是同步的。

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

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

 
 
 
  1. this.setState({
  2.   value: this.state.value + 1
  3. })
  4. this.setState({
  5.   value: this.state.value + 1
  6. })
  7. this.setState({
  8.   value: this.state.value + 1
  9. })

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

 
 
 
  1. function batchedUpdates$1(fn, a) {
  2.     var prevExecutionContext = executionContext;
  3.     executionContext |= BatchedContext;
  4.     try {
  5.       return fn(a);
  6.     } finally {
  7.       executionContext = prevExecutionContext;
  8.       if (executionContext === NoContext) {
  9.         // Flush the immediate callbacks that were scheduled during this batch
  10.         resetRenderTimer();
  11.         flushSyncCallbackQueue(); // 同步的更新
  12.       }
  13.     }
  14.   }

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

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

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

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

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

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

當然了,在concurrent 模式下,又是有所不同的。

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

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

 
 
 
  1. function scheduleUpdateOnFiber(fiber, lane, eventTime) {
  2.     // ...
  3.     if (root === workInProgressRoot) {
  4.       // ...... 
  5.     } // TO an argument to that function and this one.
  6.     if (lane === SyncLane) {  // 同步任務
  7.       if ( // 檢查當前是不是在unbatchedUpdates(非批量更新),(初次渲染的ReactDOM.render就是unbatchedUpdates)
  8.       (executionContext & LegacyUnbatchedContext) !== NoContext && // Check if we're not already rendering
  9.       (executionContext & (RenderContext | CommitContext)) === NoContext) {
  10.         // Register pending interactions on the root to avoid losing traced interaction data.
  11.         schedulePendingInteractions(root, lane); 
  12.         performSyncWorkOnRoot(root);
  13.       } else {
  14.         ensureRootIsScheduled(root, eventTime);
  15.         schedulePendingInteractions(root, lane);
  16.         if (executionContext === NoContext) {
  17.           resetRenderTimer();
  18.           flushSyncCallbackQueue();
  19.         }
  20.       }
  21.     } else { // 異步任務
  22.       // concurrent模式下是跳過了 flushSyncCallbackQueue 同步更新
  23.       // ....
  24.     } 
  25.   }

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

concurrent 模式

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

 
 
 
  1. ReactDOM.createRoot(rootNode).render()

這個模式開啟了所有的新功能。

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

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

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

  • 哪些會命中batchUpdate機制
  • 生命周期(和它調(diào)用函數(shù))
  • React中注冊的事件
  • React可以'管理入口'

新聞名稱:聊聊setState的用法,你會幾個?
標題路徑:http://www.dlmjj.cn/article/dhecpjh.html