react批量更新、同步/異步更新場(chǎng)景
React 16 到 React 19 期間,批量更新(Batch Update)機(jī)制發(fā)生了很大變化,尤其是 React 18 引入了 自動(dòng)批量更新(Automatic Batching)。
面試中經(jīng)常會(huì)問:
React16、React17、React18、React19 的批量更新區(qū)別?
哪些場(chǎng)景是同步更新?哪些是異步更新?
下面詳細(xì)講解。
一、什么是批量更新
先看代碼:
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
}很多人以為:
0 -> 1
1 -> 2
2 -> 3
實(shí)際:
最終 = 1
因?yàn)?React 會(huì)把多個(gè) state 更新合并:
Batch Update
減少:
render() render() render()
變成:
render()
提高性能。
二、React16/17 批量更新機(jī)制
React16 和 React17:
只有 React 控制的事件中才會(huì)批量更新
例如:
function App() {
const [count, setCount] = useState(0);
const click = () => {
setCount(c => c + 1);
setCount(c => c + 1);
setCount(c => c + 1);
};
return (
<button onClick={click}>
{count}
</button>
);
}
React 會(huì)批量更新:
setCount
setCount
setCount↓
render 一次
更新流程
點(diǎn)擊按鈕
↓
收集更新
↓
更新隊(duì)列
↓
統(tǒng)一計(jì)算state
↓
render
三、React16/17 哪些場(chǎng)景不是批量更新
1 setTimeout
setTimeout(() => {
setCount(c => c + 1);
setCount(c => c + 1);
});
React16/17:
render render
兩次渲染。
因?yàn)椋?/p>
setTimeout
不是 React 管理的事件
2 Promise
Promise.resolve().then(() => {
setCount(c => c + 1);
setCount(c => c + 1);
});
React16/17:
render
render
3 原生事件
document.addEventListener(
'click',
() => {
setCount(c => c + 1);
setCount(c => c + 1);
}
);
React16/17:
render
render
React16/17 總結(jié)
| 場(chǎng)景 | 是否批量更新 |
|---|---|
| React事件 | ? |
| 生命周期函數(shù) | ? |
| setTimeout | ? |
| Promise | ? |
| async/await | ? |
| 原生事件 | ? |
四、React18/19 自動(dòng)批量更新
React18 最大變化:
Automatic Batching
自動(dòng)批量更新
只要使用:
createRoot()
就開啟。
setTimeout
setTimeout(() => {
setCount(c => c + 1);
setCount(c => c + 1);
});
React18:
render 一次
Promise
Promise.resolve().then(() => {
setCount(c => c + 1);
setCount(c => c + 1);
});
React18:
render 一次
async await
async function test() {
await fetch();
setCount(c => c + 1);
setCount(c => c + 1);
}
React18:
render 一次
原生事件
document.addEventListener(
'click',
() => {
setCount(c => c + 1);
setCount(c => c + 1);
}
);
React18:
render 一次
React18/19 總結(jié)
| 場(chǎng)景 | React16/17 | React18/19 |
|---|---|---|
| React事件 | ? | ? |
| Promise | ? | ? |
| setTimeout | ? | ? |
| async/await | ? | ? |
| 原生事件 | ? | ? |
五、同步更新和異步更新
很多面試官喜歡問:
React setState 是同步還是異步?
答案:
既不是單純同步
也不是單純異步
React事件中
const click = () => {
setCount(1);
console.log(count);
}
輸出:
0
因?yàn)椋?/p>
state沒有立即更新
React先收集更新。
過程
setState
↓
放入更新隊(duì)列
↓
事件結(jié)束
↓
render
↓
state更新
所以表現(xiàn)得像:異步
六、真正同步更新 flushSync
React18:
import { flushSync } from 'react-dom';
flushSync(() => {
setCount(1);
});
console.log(count);
React立即更新。
執(zhí)行流程
flushSync
↓
立即render
↓
立即commit
↓
state更新
七、React Fiber中的更新優(yōu)先級(jí)
React16開始引入:
Fiber
更新不再是:
同步遞歸
而是:
可中斷
更新會(huì)進(jìn)入:Lane
優(yōu)先級(jí)隊(duì)列。
高優(yōu)先級(jí)
用戶輸入<input />
中優(yōu)先級(jí)
按鈕點(diǎn)擊onClick
低優(yōu)先級(jí)
列表渲染
startTransition()
startTransition(() => {
setList(bigData);
});
八、React18 Concurrent模式
React18:
const root = createRoot(
document.getElementById('root')
);
開啟并發(fā)特性。
低優(yōu)先級(jí)更新:
startTransition(() => {
setList(data);
});
高優(yōu)先級(jí):
setInput(value);
React會(huì):
先響應(yīng)輸入
↓
再渲染大列表
避免頁(yè)面卡頓。
九、面試標(biāo)準(zhǔn)答案
React16/17
React事件中會(huì)批量更新,
setTimeout、Promise、
async/await、原生事件中不會(huì)批量更新。
React18/19
引入Automatic Batching,
React事件、Promise、
setTimeout、async/await、
原生事件都會(huì)自動(dòng)批量更新。
setState同步還是異步
本質(zhì)上是同步創(chuàng)建Update對(duì)象,
異步執(zhí)行render和commit。因此表現(xiàn)為異步。
強(qiáng)制同步更新
flushSync(() => {
setState(...)
});
React18新特性
- 自動(dòng)批量更新(Automatic Batching)
- 并發(fā)渲染(Concurrent Rendering)
- startTransition
- Suspense增強(qiáng)
- Lane優(yōu)先級(jí)調(diào)度
這套內(nèi)容基本覆蓋了 React 16 → React 19 關(guān)于批量更新、同步/異步更新、Fiber 調(diào)度和面試高頻考點(diǎn)。
到此這篇關(guān)于react批量更新、同步/異步更新場(chǎng)景的文章就介紹到這了,更多相關(guān)react批量更新、同步/異步更新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Docker部署SpringBoot項(xiàng)目到云服務(wù)器的實(shí)現(xiàn)步驟
Docker作為一種輕量級(jí)的容器化技術(shù),為開發(fā)者提供了快速、便捷的部署方案,本文主要介紹了Docker部署SpringBoot項(xiàng)目到云服務(wù)器,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01
React實(shí)現(xiàn)響應(yīng)式布局的最佳實(shí)踐
在當(dāng)今的前端開發(fā)中,響應(yīng)式設(shè)計(jì)已經(jīng)成為必不可少的部分,隨著各種設(shè)備的出現(xiàn),確保我們的網(wǎng)頁(yè)在不同屏幕尺寸上展示良好,已經(jīng)成為開發(fā)者的首要任務(wù)之一,本文將介紹如何在React中實(shí)現(xiàn)響應(yīng)式布局,提供一些最佳實(shí)踐和示例代碼,幫助大家更好地理解這一概念2025-02-02
React實(shí)現(xiàn)文件上傳和斷點(diǎn)續(xù)傳功能的示例代碼
這篇文章主要為大家詳細(xì)介紹了React實(shí)現(xiàn)文件上傳和斷點(diǎn)續(xù)傳功能的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02
使用React代碼動(dòng)態(tài)生成柵格布局的方法
這篇文章主要介紹了使用React簡(jiǎn)短代碼動(dòng)態(tài)生成柵格布局的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
React官方團(tuán)隊(duì)完善原生Hook閉包陷阱
這篇文章主要為大家介紹了React官方團(tuán)隊(duì)出手,補(bǔ)齊原生Hook短板閉包陷阱的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
React修改數(shù)組對(duì)象的注意事項(xiàng)及說明
這篇文章主要介紹了React修改數(shù)組對(duì)象的注意事項(xiàng)及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
從零開始搭建一個(gè)react項(xiàng)目開發(fā)
這篇文章主要介紹了從零開始搭建一個(gè)react項(xiàng)目開發(fā),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02

