日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

深入理解React?State?原理_React

作者:YuLong~W ? 更新時(shí)間: 2022-03-27 編程語言

問題:setState 到底是同步還是異步的?

如果對 React 底層有一定了解,可以回答出 batchUpdate 批量更新概念,以及批量更新被打破的條件。

答案:有時(shí)是同步,有時(shí)是異步。

在 合成事件 和 生命周期函數(shù) 里是 異步 的在 原生事件 和 setTimeout、promise里是 同步

造成setState的異步并不是由內(nèi)部的異步代碼引起的,在本身的執(zhí)行過程中時(shí)同步的,但是合成事件和生命周期函數(shù)的調(diào)用順序在更新之前,導(dǎo)致在內(nèi)部不能直接得到更新后的值,可以用第二個(gè)參數(shù) callback 來獲取。

具體解釋:可參考setState的執(zhí)行過程

類組件state

setState(obj,callback)

  • 第一個(gè)參數(shù):當(dāng) obj 為一個(gè)對象,則為即將合并的 state ;如果 obj 是一個(gè)函數(shù),那么當(dāng)前組件的 state 和 props 將作為參數(shù),返回值用于合并新的 state。
  • 第二個(gè)參數(shù) callback :callback 為一個(gè)函數(shù),函數(shù)執(zhí)行上下文中可以獲取當(dāng)前 setState 更新后的最新 state 的值,可以作為依賴 state 變化的副作用函數(shù),可以用來做一些基于 DOM 的操作。

一次事件中觸發(fā)一次如上 setState ,在 React 底層執(zhí)行過程:

render 階段 render 函數(shù)執(zhí)行 -> commit 階段真實(shí) DOM 替換 -> setState 回調(diào)函數(shù)執(zhí)行 callback

在這里插入圖片描述

首先,setState 會(huì)產(chǎn)生當(dāng)前更新的優(yōu)先級(jí)(老版本用 expirationTime ,新版本用 lane )。接下來 React 會(huì)從 fiber Root 根部 fiber 向下調(diào)和子節(jié)點(diǎn),調(diào)和階段將對比發(fā)生更新的地方,更新對比 expirationTime ,找到發(fā)生更新的組件,合并 state,然后觸發(fā) render 函數(shù),得到新的 UI 視圖層,完成 render 階段。接下來到 commit 階段,commit 階段,替換真實(shí) DOM ,完成此次更新流程。此時(shí)仍然在 commit 階段,會(huì)執(zhí)行 setState 中 callback 函數(shù),到此為止完成了一次 setState 全過程。

setState原理揭秘

本質(zhì):React 底層調(diào)用 Updater 對象上的 enqueueSetState 方法

enqueueSetState():創(chuàng)建一個(gè)update,放入當(dāng)前 fiber對象 的待更新隊(duì)列中,最后開啟調(diào)度更新,進(jìn)入更新流程。

在這里插入圖片描述

React 的 batchUpdate 批量更新

目的:多次 setstate 會(huì)讓邏輯多停留在 js 運(yùn)行層面,阻塞了瀏覽器繪制,因此需要批量更新

batchedEventUpdates ():

在這里插入圖片描述

分析流程:

  • React 事件執(zhí)行前通過?isBatchingEventUpdates=true?打開開關(guān),開啟事件批量更新
  • 當(dāng)事件結(jié)束,通過?isBatchingEventUpdates=false?關(guān)閉開關(guān)
  • 在?scheduleUpdateOnFiber?中根據(jù)這個(gè)開關(guān)來確定是否進(jìn)行批量更新

1)異步環(huán)境下,繼續(xù)開啟批量更新模式:

異步操作里面的批量更新規(guī)則會(huì)被打破,因此提供了手動(dòng)批量更新方法: unstable_batchedUpdates

2)提升更新優(yōu)先級(jí):

提供了方法: flushSync,可以將回調(diào)函數(shù)中的更新任務(wù),放在一個(gè)較高的優(yōu)先級(jí)中優(yōu)先執(zhí)行

補(bǔ)充:flushSync 在同步條件下,會(huì)合并之前的 setState | useState

3)總結(jié):React 同一級(jí)別更新優(yōu)先級(jí) 關(guān)系是:

flushSync 中的 setState > 正常執(zhí)行上下文中 setState > 異步 setTimeout ,Promise 中的 setState

函數(shù)組件state

const [ state , dispatch ] = useState(initData)

  • ① state 目的提供給 UI ,作為渲染視圖的數(shù)據(jù)源
  • ② dispatch 改變 state 的函數(shù),可以理解為推動(dòng)函數(shù)組件渲染的渲染函數(shù)
  • ③ initData 初始值

initData的初始值

  • 第一種情況是非函數(shù),將作為 state 初始化的值
  • 第二種情況是函數(shù),函數(shù)的返回值作為 useState 初始化的值

dispatch的參數(shù)

  • 第一種非函數(shù)情況,此時(shí)將作為新的值,賦予給 state,作為下一次渲染使用
  • 第二種是函數(shù)的情況,如果 dispatch 的參數(shù)為一個(gè)函數(shù),這里可以稱它為reducer,reducer 參數(shù),是上一次返回最新的 state,返回值作為新的 state

監(jiān)聽 state 變化

useEffect :??梢园?state 作為 依賴項(xiàng) 傳入 useEffect 第二個(gè)參數(shù) deps ,但是注意 useEffect 初始化會(huì)默認(rèn)執(zhí)行一次

dispatch更新特點(diǎn)

與類組件一樣,但是當(dāng)調(diào)用改變 state 的函數(shù)dispatch,在本次函數(shù)執(zhí)行上下文中,是獲取不到最新的 state 值的

在這里插入圖片描述


原因:函數(shù)組件更新就是函數(shù)的執(zhí)行,在一次執(zhí)行過程中,函數(shù)內(nèi)部所有變量重新聲明,所以改變的 state 只有在下一次函數(shù)執(zhí)行時(shí)才更新。

useState 原理在之后 Hooks 講解

問:類組件中的 setState 和函數(shù)組件中的 useState 有什么異同?

答:相同點(diǎn):

  • 原理:setState 和 useState 更新視圖,底層都調(diào)用了 scheduleUpdateOnFiber 方法,而且事件驅(qū)動(dòng)情況下都有批量更新規(guī)則
  • 語法:第一個(gè)參數(shù)都可以傳入函數(shù)

不同點(diǎn):

  • 在不是 pureComponent 組件模式下, setState 不會(huì)淺比較兩次 state 的值。只要調(diào)用 setState 就會(huì)執(zhí)行更新。但是 useState 中 dispatchAction 會(huì)默認(rèn)比較兩次state是否相同來更新組件
  • setState 有專門監(jiān)聽 state 變化的回調(diào)函數(shù) callback,可以獲取最新 state。但是 useState 只能通過 useEffect 來執(zhí)行 state 變化引起的副作用
  • setState 在底層處理邏輯時(shí)將舊 state 進(jìn)行合并處理,而 useState 是重新賦值

原文鏈接:https://blog.csdn.net/weixin_45654582/article/details/121237439

欄目分類
最近更新