淺談React多個setState會調(diào)用幾次
1. 兩個setState,調(diào)用幾次?
如下代碼所示,state中有一個count。對按鈕綁定了點擊事件,事件中執(zhí)行了兩次setState,每次都將count的值加1。
當點擊按鈕時,setState會執(zhí)行幾次?render()會執(zhí)行幾次?
答案:都是1次。
state = { count: 0 };
handleClick = () => {
this.setState({ count: this.state.count + 1 });
this.setState({ count: this.state.count + 1 });
};
render() {
console.log(`render`);
return (
<>
<div>當前計數(shù):{this.state.count}</div>
<button onClick={this.handleClick}>add</button>
</>
);
}
按照常理來說,第一次點擊按鈕時,由于執(zhí)行了兩次兩次setState,每次都將count的值進行加1,render()應(yīng)該會執(zhí)行兩次,最后count的值應(yīng)該是2。但是 React 并不是這么執(zhí)行的。
以上代碼放到瀏覽器運行一下即可:

最開始時,頁面顯示count的值為0,控制臺打印出render,這是 React 首次渲染時打印的。當點擊完按鈕后,頁面顯示count值是1,同時也只打印了1個render,說明在這過程中 React 只執(zhí)行了一次setState,只執(zhí)行了一次render()渲染操作。
原因在于,React 內(nèi)部將同一事件響應(yīng)函數(shù)中的多個setState進行合并,減少setState的調(diào)用次數(shù),也就能減少渲染的次數(shù),提高性能。
這也就解釋了上述代碼,為什么最后count的值是1,因為 React 將兩個setState進行了合并,最終只執(zhí)行了1次,render()也只執(zhí)行了一次。
2. 兩個setState,調(diào)用的是哪一個?
但上述代碼沒有驗證,React 合并后,到底執(zhí)行的是哪一次setState。如下代碼所示,將第二個setState中,對count的操作改為加2,其余代碼保持不變:
state = { count: 0 };
handleClick = () => {
this.setState({ count: this.state.count + 1 });
this.setState({ count: this.state.count + 2 }); // 改為+2
};
render() {
console.log(`render`);
return (
<>
<div>當前計數(shù):{this.state.count}</div>
<button onClick={this.handleClick}>add</button>
</>
);
}
再次放到瀏覽器中執(zhí)行:

結(jié)果顯示,點擊按鈕后,count的值最終變成了2,也就是進行了+2的操作,render()也只執(zhí)行了1次。這就說明 React 在合并多個setState時,若出現(xiàn)同名屬性,會將后面的同名屬性覆蓋掉前面的同名屬性。可以這么理解,對于同名屬性,最終執(zhí)行的的是最后的setState中的屬性。
3. 兩個setState放在setTimeout中?
若在點擊事件函數(shù)中,添加一個定時器setTimeout,在定時器中執(zhí)行兩次setState操作,結(jié)果又將如何?如下代碼,事件處理函數(shù)中,寫了一個定時器setTimeout,將兩次setState放入setTimeout中。
state = { count: 0 };
handleClick = () => {
setTimeout(() => {
this.setState({ count: this.state.count + 1 });
this.setState({ count: this.state.count + 2 });
}, 0);
};
render() {
console.log(`render`);
return (
<>
<div>當前計數(shù):{this.state.count}</div>
<button onClick={this.handleClick}>add</button>
</>
);
}
運行結(jié)果:

結(jié)果顯示,點擊按鈕后,count的值最終變成了3,也就+1和+2的操作都執(zhí)行了,render()也執(zhí)行了2次。
這是因為在 React 的合成事件和生命周期函數(shù)中直接調(diào)用setState,會交由 React 的性能優(yōu)化機制管理,合并多個setState。而在原生事件、setTimeout中調(diào)用setState,是不受 React 管理的,故并不會合并多個setState,寫了幾次setState,就會調(diào)用幾次setState。
4. 總結(jié)
在 React 中直接使用的事件,如onChange、onClick等,都是由 React 封裝后的事件,是合成事件,由 React 管理。
React 對于合成事件和生命周期函數(shù),有一套性能優(yōu)化機制,會合并多個setState,若出現(xiàn)同名屬性,會將后面的同名屬性覆蓋掉前面的同名屬性。
若越過 React 的性能優(yōu)化機制,在原生事件、setTimeout中使用setState,就不歸 React 管理了,寫了幾次setState,就會調(diào)用幾次setState。
到此這篇關(guān)于淺談React多個setState會調(diào)用幾次的文章就介紹到這了,更多相關(guān)淺談React多個setState會調(diào)用幾次內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React Hook 'useEffect' is call
這篇文章主要為大家介紹了React Hook 'useEffect' is called in function報錯解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12
React使用hook如何實現(xiàn)數(shù)據(jù)雙向綁定
這篇文章主要介紹了React使用hook如何實現(xiàn)數(shù)據(jù)雙向綁定方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
React+Node實現(xiàn)大文件分片上傳、斷點續(xù)傳秒傳思路
本文主要介紹了React+Node實現(xiàn)大文件分片上傳、斷點續(xù)傳秒傳思路,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02
解析TypeError:import_react_native.AppState.removeEventListener
這篇文章主要為大家介紹了TypeError:import_react_native.AppState.removeEventListener?is?not?a?function問題解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09
react 不用插件實現(xiàn)數(shù)字滾動的效果示例
這篇文章主要介紹了react 不用插件實現(xiàn)數(shù)字滾動的效果示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04

