React的setState批量更新機(jī)制詳解
1. 批量更新的基本概念
批量更新(Batching)是指 React 將多個(gè) setState 調(diào)用合并為單個(gè)更新,從而減少組件重新渲染的次數(shù)。
示例代碼:
class MyComponent extends React.Component {
state = { count: 0 };
handleClick = () => {
this.setState({ count: this.state.count + 1 }); // 不會(huì)立即更新
this.setState({ count: this.state.count + 1 }); // 不會(huì)立即更新
// React 會(huì)將這兩個(gè) setState 合并
};
render() {
return <button onClick={this.handleClick}>Count: {this.state.count}</button>;
}
}
2. 批量更新的實(shí)現(xiàn)原理
2.1 更新隊(duì)列機(jī)制
React 維護(hù)一個(gè)待處理的 state 更新隊(duì)列,而不是立即應(yīng)用每個(gè) setState:

2.2 具體過(guò)程
- 更新入隊(duì):每次調(diào)用
setState,更新會(huì)被加入一個(gè)待處理隊(duì)列 - 批量處理:在事件處理函數(shù)執(zhí)行結(jié)束時(shí),React 會(huì)批量處理所有隊(duì)列中的更新
- 合并更新:對(duì)于同一 state 鍵的多個(gè)更新,React 會(huì)進(jìn)行淺合并
- 觸發(fā)渲染:最終只進(jìn)行一次重新渲染
3. 批量更新的觸發(fā)時(shí)機(jī)
3.1 自動(dòng)批處理場(chǎng)景
- React 事件處理函數(shù)(如 onClick)
- 生命周期方法
- React 能控制的入口點(diǎn)
3.2 不會(huì)自動(dòng)批處理的情況
- 異步代碼:setTimeout、Promise、原生事件處理等
- React 18 之前:只有在 React 事件處理函數(shù)中才會(huì)批處理
// 不會(huì)批處理的例子(React 17及之前)
handleClick = () => {
setTimeout(() => {
this.setState({ count: this.state.count + 1 });
this.setState({ count: this.state.count + 1 });
// React 17中會(huì)觸發(fā)兩次渲染
}, 0);
};
4. React 18 的自動(dòng)批處理改進(jìn)
React 18 引入了全自動(dòng)批處理,覆蓋更多場(chǎng)景:
// 在React 18中,這會(huì)批量處理
fetchData().then(() => {
setState1();
setState2();
// 只會(huì)觸發(fā)一次渲染
});
5. 強(qiáng)制同步更新的方法
如果需要立即獲取更新后的狀態(tài),可以使用回調(diào)函數(shù)形式或 flushSync(React 18+):
// 回調(diào)函數(shù)形式
this.setState({ count: this.state.count + 1 }, () => {
console.log('更新后的值:', this.state.count);
});
// React 18的flushSync
import { flushSync } from 'react-dom';
flushSync(() => {
this.setState({ count: this.state.count + 1 });
});
// 這里state已經(jīng)更新
6. 函數(shù)式組件的批量更新
函數(shù)式組件中 useState 也有類似的批量更新行為:
function MyComponent() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(c => c + 1); // 更新1
setCount(c => c + 1); // 更新2
// React會(huì)批量處理,最終count增加2
};
return <button onClick={handleClick}>{count}</button>;
}
7. 源碼層面的簡(jiǎn)要分析
React 內(nèi)部通過(guò) enqueueUpdate 函數(shù)將更新加入隊(duì)列:
// 偽代碼簡(jiǎn)化版
function enqueueUpdate(component, partialState) {
if (!batchingStrategy.isBatchingUpdates) {
// 如果不處于批量模式,立即更新
batchingStrategy.batchedUpdates(enqueueUpdate, component, partialState);
return;
}
// 否則加入隊(duì)列
dirtyComponents.push(component);
component._pendingStateQueue.push(partialState);
}
8. 為什么需要批量更新?
- 性能優(yōu)化:減少不必要的渲染次數(shù)
- 保證一致性:避免中間狀態(tài)導(dǎo)致的UI不一致
- 提升用戶體驗(yàn):更流暢的界面更新
9. 注意事項(xiàng)
- 不要依賴
this.state獲取最新值,因?yàn)樗赡苓€未更新 - 對(duì)于連續(xù)依賴前一次狀態(tài)的更新,使用函數(shù)形式:
this.setState(prevState => ({ count: prevState.count + 1 }));
- 在React 18之前,異步操作中的多個(gè)
setState不會(huì)批量處理
React 的批量更新機(jī)制是其高效渲染的核心特性之一,理解這一機(jī)制有助于編寫(xiě)更高效的React代碼和避免常見(jiàn)陷阱。
到此這篇關(guān)于React的setState批量更新機(jī)制詳解的文章就介紹到這了,更多相關(guān)React setState批量更新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react redux中如何獲取store數(shù)據(jù)并將數(shù)據(jù)渲染出來(lái)
這篇文章主要介紹了react redux中如何獲取store數(shù)據(jù)并將數(shù)據(jù)渲染出來(lái),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
react實(shí)現(xiàn)復(fù)選框全選和反選組件效果
這篇文章主要為大家詳細(xì)介紹了react實(shí)現(xiàn)復(fù)選框全選和反選組件效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
React Hook 監(jiān)聽(tīng)localStorage更新問(wèn)題
這篇文章主要介紹了React Hook 監(jiān)聽(tīng)localStorage更新問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10
React 條件渲染最佳實(shí)踐小結(jié)(7種)
這篇文章主要介紹了React 條件渲染最佳實(shí)踐小結(jié)(7種),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
詳解React項(xiàng)目中eslint使用百度風(fēng)格
這篇文章主要介紹了React項(xiàng)目中eslint使用百度風(fēng)格,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
ReactNative?狀態(tài)管理redux使用詳解
這篇文章主要介紹了ReactNative?狀態(tài)管理redux使用詳解2023-03-03
react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法
本篇文章主要介紹了react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12

