以后没有React Concurrent Mode了
相信很多关注React
的朋友都知道Concurrent Mode
,他是React
渐进升级策略的产物。
即然是策略,那就有可能调整,这不,根据What happened to concurrent mode?[1],在v18
中将不会有Concurrent Mode
了。
本文让我们一起了解React
渐进升级策略的演进过程。
React新老架构的区别
可以认为采用Fiber架构
前的React
只支持一种优先级:同步优先级
,即所有更新是“同步、不可中断”的形式。
采用Fiber架构
后的React
支持包括同步优先级
在内的多种优先级,或者说新架构支持并发更新
。
所以新架构可以模拟老架构的运行机制(即不开启并发更新
)。
当新架构开启并发更新
后,就能使用React
为了解决CPU的瓶颈
、IO的瓶颈
而设计的并发特性
(Concurrent Feature),比如:
useDeferredValue
useTransition
全功能的Suspense
React所有版本可能的情况
当前所有React
版本一定属于如下情况之一:
v15及之前的老架构
v16之后的新架构,未开启并发更新,与情况1行为一致
v16之后的新架构,未开启并发更新,但是启用了一些新功能(比如
Automatic Batching
)v16之后的新架构,开启并发更新
v16、v17默认属于情况2。
之所以划分多种情况,是因为情况4的React
一些行为异于情况1、2、3(比如部分以componentWill
开头的生命周期函数的调用时机发生变化),也就是说开启并发更新
可能造成老代码不兼容。
为了让广大开发者能够平滑过渡,React
团队采用了「渐进升级」方案。
早期的渐进升级策略
v16.3新增了StrictMode
,对开发者编写的「不符合并发更新规范的代码」作出提示,逐步引导开发者写出规范代码。
此时React
团队的「渐进升级」策略是:让页面中可以同时存在三种模式的应用,具体如下:
Legacy
模式,通过ReactDOM.render(
创建的应用遵循该模式。默认关闭, rootNode) StrictMode
,表现同情况2Blocking
模式,通过ReactDOM.createBlockingRoot(rootNode).render(
创建的应用遵循该模式,作为从) Legacy
向Concurrent
过渡的中间模式,默认开启StrictMode
,表现同情况3Concurrent
模式,通过ReactDOM.createRoot(rootNode).render(
创建的应用遵循该模式,默认开启) StrictMode
,表现同情况4
在v17之前,大多数事件会冒泡到HTML
元素,为了让同一个页面下不同应用独立,v17之后事件会冒泡到应用所在根元素。
所以v17也被称为「垫脚石」版本,他是为「开启并发更新」做铺垫的版本。
当前的渐进升级策略
但是,根据社区的反馈,React团队意识到当前的「渐进升级」策略存在问题。
这三种模式影响的是整个应用,从Legacy
升级到Blocking
后,由于开启StrictMode
,整个应用的「并发不兼容警告」都会上报。从这个角度看,并没有起到「渐进升级」的目的。
另一方面,开发者从新架构中获益更多是由于使用了并发特性
,即然新架构支持「开关并发更新」,完全可以在使用了并发特性
后再开启并发更新
。这样就只需在「使用了并发特性的组件」部分启用StrictMode
。
相比划分三种模式,这种以「是否使用并发特性」作为是否开启并发更新
的依据,更符合「渐进升级」中「渐进」的理念。
所以在v18中,不再有三种模式,统一使用ReactDOM.createRoot(rootNode).render(
创建应用。当不使用并发特性时,表现如情况3。使用并发特性后,表现如情况4。
总结
一句话总结:v18
以后只会有并发特性
,不会有并发模式
。
作为一个发展了8年之久的前端框架,要想推进社区完成带有breaking change
的迭代升级,注定是困难的。
我们也看到了React
团队在此确实付出很多心血。
想问问各位,还学得动么?
参考资料
What happened to concurrent mode?: https://github.com/reactwg/react-18/discussions/64