淺談React多個(gè)setState會(huì)調(diào)用幾次
1. 兩個(gè)setState,調(diào)用幾次?
如下代碼所示,state
中有一個(gè)count
。對(duì)按鈕綁定了點(diǎn)擊事件,事件中執(zhí)行了兩次setState
,每次都將count
的值加1
。
當(dāng)點(diǎn)擊按鈕時(shí),setState
會(huì)執(zhí)行幾次?render()
會(huì)執(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>當(dāng)前計(jì)數(shù):{this.state.count}</div> <button onClick={this.handleClick}>add</button> </> ); }
按照常理來(lái)說(shuō),第一次點(diǎn)擊按鈕時(shí),由于執(zhí)行了兩次兩次setState
,每次都將count
的值進(jìn)行加1
,render()
應(yīng)該會(huì)執(zhí)行兩次,最后count
的值應(yīng)該是2。但是 React 并不是這么執(zhí)行的。
以上代碼放到瀏覽器運(yùn)行一下即可:
最開(kāi)始時(shí),頁(yè)面顯示count
的值為0
,控制臺(tái)打印出render
,這是 React 首次渲染時(shí)打印的。當(dāng)點(diǎn)擊完按鈕后,頁(yè)面顯示count
值是1
,同時(shí)也只打印了1
個(gè)render
,說(shuō)明在這過(guò)程中 React 只執(zhí)行了一次setState
,只執(zhí)行了一次render()
渲染操作。
原因在于,React 內(nèi)部將同一事件響應(yīng)函數(shù)中的多個(gè)setState
進(jìn)行合并,減少setState
的調(diào)用次數(shù),也就能減少渲染的次數(shù),提高性能。
這也就解釋了上述代碼,為什么最后count
的值是1
,因?yàn)?React 將兩個(gè)setState
進(jìn)行了合并,最終只執(zhí)行了1
次,render()
也只執(zhí)行了一次。
2. 兩個(gè)setState,調(diào)用的是哪一個(gè)?
但上述代碼沒(méi)有驗(yàn)證,React 合并后,到底執(zhí)行的是哪一次setState
。如下代碼所示,將第二個(gè)setState
中,對(duì)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>當(dāng)前計(jì)數(shù):{this.state.count}</div> <button onClick={this.handleClick}>add</button> </> ); }
再次放到瀏覽器中執(zhí)行:
結(jié)果顯示,點(diǎn)擊按鈕后,count
的值最終變成了2
,也就是進(jìn)行了+2
的操作,render()
也只執(zhí)行了1
次。這就說(shuō)明 React 在合并多個(gè)setState
時(shí),若出現(xiàn)同名屬性,會(huì)將后面的同名屬性覆蓋掉前面的同名屬性。可以這么理解,對(duì)于同名屬性,最終執(zhí)行的的是最后的setState
中的屬性。
3. 兩個(gè)setState放在setTimeout中?
若在點(diǎn)擊事件函數(shù)中,添加一個(gè)定時(shí)器setTimeout
,在定時(shí)器中執(zhí)行兩次setState
操作,結(jié)果又將如何?如下代碼,事件處理函數(shù)中,寫(xiě)了一個(gè)定時(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>當(dāng)前計(jì)數(shù):{this.state.count}</div> <button onClick={this.handleClick}>add</button> </> ); }
運(yùn)行結(jié)果:
結(jié)果顯示,點(diǎn)擊按鈕后,count
的值最終變成了3
,也就+1
和+2
的操作都執(zhí)行了,render()
也執(zhí)行了2
次。
這是因?yàn)樵?React 的合成事件和生命周期函數(shù)中直接調(diào)用setState
,會(huì)交由 React 的性能優(yōu)化機(jī)制管理,合并多個(gè)setState
。而在原生事件、setTimeout
中調(diào)用setState
,是不受 React 管理的,故并不會(huì)合并多個(gè)setState
,寫(xiě)了幾次setState
,就會(huì)調(diào)用幾次setState
。
4. 總結(jié)
在 React 中直接使用的事件,如onChange
、onClick
等,都是由 React 封裝后的事件,是合成事件,由 React 管理。
React 對(duì)于合成事件和生命周期函數(shù),有一套性能優(yōu)化機(jī)制,會(huì)合并多個(gè)setState
,若出現(xiàn)同名屬性,會(huì)將后面的同名屬性覆蓋掉前面的同名屬性。
若越過(guò) React 的性能優(yōu)化機(jī)制,在原生事件、setTimeout
中使用setState
,就不歸 React 管理了,寫(xiě)了幾次setState
,就會(huì)調(diào)用幾次setState
。
到此這篇關(guān)于淺談React多個(gè)setState會(huì)調(diào)用幾次的文章就介紹到這了,更多相關(guān)淺談React多個(gè)setState會(huì)調(diào)用幾次內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于antd的autocomplete的二次封裝查詢(xún)示例
這篇文章主要為大家介紹了基于antd的autocomplete的二次封裝查詢(xún)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08React路由鑒權(quán)的實(shí)現(xiàn)方法
這篇文章主要介紹了React路由鑒權(quán)的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09解決React初始化加載組件會(huì)渲染兩次的問(wèn)題
這篇文章主要介紹了解決React初始化加載組件會(huì)渲染兩次的問(wèn)題,文中有出現(xiàn)這種現(xiàn)象的原因及解決方法,感興趣的同學(xué)跟著小編一起來(lái)看看吧2023-08-08詳解react使用react-bootstrap當(dāng)輪子造車(chē)
本篇文章主要介紹了詳解react使用react-bootstrap當(dāng)輪子造車(chē),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-08-08React實(shí)現(xiàn)簡(jiǎn)單登錄的項(xiàng)目實(shí)踐
登錄、注冊(cè)、找回密碼是前端項(xiàng)目經(jīng)常遇到的需求,本文主要介紹了React實(shí)現(xiàn)簡(jiǎn)單登錄的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01react中hooks使用useState的更新不觸發(fā)dom更新問(wèn)題及解決
這篇文章主要介紹了react中hooks使用useState的更新不觸發(fā)dom更新問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01react+redux的升級(jí)版todoList的實(shí)現(xiàn)
本篇文章主要介紹了react+redux的升級(jí)版todoList的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12