以后没有React Concurrent Mode了

共 1897字,需浏览 4分钟

 ·

2021-11-19 18:43

相信很多关注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版本一定属于如下情况之一:

  1. v15及之前的老架构

  2. v16之后的新架构,未开启并发更新,与情况1行为一致

  3. v16之后的新架构,未开启并发更新,但是启用了一些新功能(比如Automatic Batching

  4. v16之后的新架构,开启并发更新

v16、v17默认属于情况2。

之所以划分多种情况,是因为情况4的React一些行为异于情况1、2、3(比如部分以componentWill开头的生命周期函数的调用时机发生变化),也就是说开启并发更新可能造成老代码不兼容。

为了让广大开发者能够平滑过渡,React团队采用了「渐进升级」方案。

早期的渐进升级策略

v16.3新增了StrictMode,对开发者编写的「不符合并发更新规范的代码」作出提示,逐步引导开发者写出规范代码。

此时React团队的「渐进升级」策略是:让页面中可以同时存在三种模式的应用,具体如下:

  1. Legacy模式,通过ReactDOM.render(, rootNode)创建的应用遵循该模式。默认关闭StrictMode,表现同情况2

  2. Blocking模式,通过ReactDOM.createBlockingRoot(rootNode).render()创建的应用遵循该模式,作为从LegacyConcurrent过渡的中间模式,默认开启StrictMode,表现同情况3

  3. Concurrent模式,通过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团队在此确实付出很多心血。

想问问各位,还学得动么?

参考资料

[1]

What happened to concurrent mode?: https://github.com/reactwg/react-18/discussions/64

浏览 11
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报