以后沒有 React Concurrent Mode了
大家好,我卡頌。
相信很多關(guān)注React的朋友都知道Concurrent Mode,他是React漸進(jìn)升級策略的產(chǎn)物。
即然是策略,那就有可能調(diào)整,這不,根據(jù)What happened to concurrent mode?[1],在v18中將不會有Concurrent Mode了。
本文讓我們一起了解React漸進(jìn)升級策略的演進(jìn)過程。
React新老架構(gòu)的區(qū)別
可以認(rèn)為采用Fiber架構(gòu)前的React只支持一種優(yōu)先級:同步優(yōu)先級,即所有更新是“同步、不可中斷”的形式。
采用Fiber架構(gòu)后的React支持包括同步優(yōu)先級在內(nèi)的多種優(yōu)先級,或者說新架構(gòu)支持并發(fā)更新。
所以新架構(gòu)可以模擬老架構(gòu)的運(yùn)行機(jī)制(即不開啟并發(fā)更新)。
當(dāng)新架構(gòu)開啟并發(fā)更新后,就能使用React為了解決CPU的瓶頸、IO的瓶頸而設(shè)計(jì)的并發(fā)特性(Concurrent Feature),比如:
- useDeferredValue
- useTransition
- 全功能的Suspense
React所有版本可能的情況
當(dāng)前所有React版本一定屬于如下情況之一:
- v15及之前的老架構(gòu)
- v16之后的新架構(gòu),未開啟并發(fā)更新,與情況1行為一致
- v16之后的新架構(gòu),未開啟并發(fā)更新,但是啟用了一些新功能(比如Automatic Batching)
- v16之后的新架構(gòu),開啟并發(fā)更新
v16、v17默認(rèn)屬于情況2。
之所以劃分多種情況,是因?yàn)榍闆r4的React一些行為異于情況1、2、3(比如部分以componentWill開頭的生命周期函數(shù)的調(diào)用時(shí)機(jī)發(fā)生變化),也就是說開啟并發(fā)更新可能造成老代碼不兼容。
為了讓廣大開發(fā)者能夠平滑過渡,React團(tuán)隊(duì)采用了「漸進(jìn)升級」方案。
早期的漸進(jìn)升級策略
v16.3新增了StrictMode,對開發(fā)者編寫的「不符合并發(fā)更新規(guī)范的代碼」作出提示,逐步引導(dǎo)開發(fā)者寫出規(guī)范代碼。
此時(shí)React團(tuán)隊(duì)的「漸進(jìn)升級」策略是:讓頁面中可以同時(shí)存在三種模式的應(yīng)用,具體如下:
- Legacy模式,通過ReactDOM.render(
, rootNode)創(chuàng)建的應(yīng)用遵循該模式。默認(rèn)關(guān)閉StrictMode,表現(xiàn)同情況2 - Blocking模式,通過ReactDOM.createBlockingRoot(rootNode).render(
)創(chuàng)建的應(yīng)用遵循該模式,作為從Legacy向Concurrent過渡的中間模式,默認(rèn)開啟StrictMode,表現(xiàn)同情況3 - Concurrent模式,通過ReactDOM.createRoot(rootNode).render(
)創(chuàng)建的應(yīng)用遵循該模式,默認(rèn)開啟StrictMode,表現(xiàn)同情況4
三種模式可用特性對比
在v17之前,大多數(shù)事件會冒泡到HTML元素,為了讓同一個(gè)頁面下不同應(yīng)用獨(dú)立,v17之后事件會冒泡到應(yīng)用所在根元素。
所以v17也被稱為「墊腳石」版本,他是為「開啟并發(fā)更新」做鋪墊的版本。
當(dāng)前的漸進(jìn)升級策略
但是,根據(jù)社區(qū)的反饋,React團(tuán)隊(duì)意識到當(dāng)前的「漸進(jìn)升級」策略存在問題。
這三種模式影響的是整個(gè)應(yīng)用,從Legacy升級到Blocking后,由于開啟StrictMode,整個(gè)應(yīng)用的「并發(fā)不兼容警告」都會上報(bào)。從這個(gè)角度看,并沒有起到「漸進(jìn)升級」的目的。
另一方面,開發(fā)者從新架構(gòu)中獲益更多是由于使用了并發(fā)特性,即然新架構(gòu)支持「開關(guān)并發(fā)更新」,完全可以在使用了并發(fā)特性后再開啟并發(fā)更新。這樣就只需在「使用了并發(fā)特性的組件」部分啟用StrictMode。
相比劃分三種模式,這種以「是否使用并發(fā)特性」作為是否開啟并發(fā)更新的依據(jù),更符合「漸進(jìn)升級」中「漸進(jìn)」的理念。
所以在v18中,不再有三種模式,統(tǒng)一使用ReactDOM.createRoot(rootNode).render(
總結(jié)
一句話總結(jié):v18以后只會有并發(fā)特性,不會有并發(fā)模式。
作為一個(gè)發(fā)展了8年之久的前端框架,要想推進(jìn)社區(qū)完成帶有breaking change的迭代升級,注定是困難的。
我們也看到了React團(tuán)隊(duì)在此確實(shí)付出很多心血。
想問問各位,還學(xué)得動么?
參考資料
[1]What happened to concurrent mode?:
https://github.com/reactwg/react-18/discussions/64