前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React 18不再依赖Concurrent Mode开启并发更新了

React 18不再依赖Concurrent Mode开启并发更新了

作者头像
公众号@魔术师卡颂
发布2021-11-23 09:49:26
1.1K0
发布2021-11-23 09:49:26
举报
文章被收录于专栏:魔术师卡颂魔术师卡颂

大家好,我卡颂。 相信很多关注React进展的朋友都了解Concurrent Mode,他是「渐进升级」策略的产物。

由于策略调整,根据What happened to concurrent mode?[1],在v18中将不会有Concurrent Mode了。

没有Concurrent Mode,那该如何使用并发更新呢?

一句话总结:在v18中,不再有三种模式,而是以「是否使用并发特性」作为「是否开启并发更新」的依据。

更详细的解释,让我们一起从React渐进升级策略的演进过程中寻找答案。

React有多少种架构?

从最老的版本到当前的v18,市面上有多少个版本的React

可以从架构角度来概括下,当前一共有两种架构:

  • 采用不可中断的「递归」方式更新的Stack Reconciler(老架构)
  • 采用可中断的「遍历」方式更新的Fiber Reconciler(新架构)

新架构可以选择是否开启并发更新,所以当前市面上所有React版本一定属于如下一种情况:

  1. 老架构(v15及之前版本)
  2. 新架构,未开启并发更新,与情况1行为一致(v16、v17默认属于这种情况)
  3. 新架构,未开启并发更新,但是启用了一些新功能(比如Automatic Batching
  4. 新架构,开启并发更新

理想与现实的差距

React团队的愿景是:

使用老版本的开发者可以逐步升级到新版,即从情况1、2、3向情况4升级。

但是这中间存在极大的阻力,因为情况4的React一些行为异于情况1、2、3。

比如如下三个生命周期函数在情况4的React下是“不安全的”:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

贸然升级可能造成老代码不兼容。

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

渐进升级第一步

「渐进升级」方案的第一步是规范代码。

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

比如,使用上述「不安全的」生命周期函数时会产生如下报错信息:

StrictMode下使用不安全生命周期函数报错

渐进升级第二步

下一步,React团队让不同情况的React可以在同一个页面共存,借此可以让情况4的React逐步渗入原有的项目。

具体做法是提供三种开发模式:

  1. Legacy模式,通过ReactDOM.render(<App />, rootNode)创建的应用遵循该模式。默认关闭StrictMode,表现同情况2
  2. Blocking模式,通过ReactDOM.createBlockingRoot(rootNode).render(<App />)创建的应用遵循该模式,作为从LegacyConcurrent过渡的中间模式,默认开启StrictMode,表现同情况3
  3. Concurrent模式,通过ReactDOM.createRoot(rootNode).render(<App />)创建的应用遵循该模式,默认开启StrictMode,表现同情况4

3种模式可用特性对比

为了让不同模式的应用可以在同一个页面内工作,需要调整一些底层实现。

比如:调整之前,大多数事件会统一冒泡到HTML元素,调整后事件会冒泡到应用所在根元素

这些调整工作发生在v17,所以v17也被称作为「开启并发更新」做铺垫的「垫脚石」版本。

最新的渐进升级策略

时间前进到2021年6月8日,v18工作组成立。

在与社区进行大量沟通后,React团队意识到当前的「渐进升级」策略存在两方面问题。

原因一

首先,由于模式影响的是整个应用,所以无法在同一个应用中完成渐进升级。

举个例子,开发者将应用中ReactDOM.render改为ReactDOM.createBlockingRoot,从Legacy模式切换到Blocking模式,这会自动开启StrictMode

此时,整个应用的「并发不兼容警告」都会上报,开发者还是需要修改整个应用。

从这个角度看,并没有起到「渐进升级」的目的。

原因二

其次,React团队发现:开发者从新架构中获益,更多是由于使用了并发特性Concurrent Feature)。

并发特性指开启并发更新后才能使用的特性,比如:

  • useDeferredValue
  • useTransition

所以,可以默认情况下仍使用同步更新,在使用了并发特性后再开启并发更新

在v18中运行如下代码:

代码语言:javascript
复制
const App = () => {
  const [count, updateCount] = useState(0);
  const [isPending, startTransition] = useTransition();

  const onClick = () => {
    // 使用了并发特性useTransition
    startTransition(() => {
      // 本次更新是并发更新
      updateCount((count) => count + 1);
    });
  };
  return <h3 onClick={onClick}>{count}</h3>;
};

由于updateCountstartTransition的回调函数中执行(使用了并发特性),所以updateCount会触发并发更新

如果updateCount没有作为startTransition的回调函数执行,那么updateCount将触发默认的同步更新

你可以观察这两种情况是否开启时间切片来区分是否是并发更新,完整代码见Demo地址[2]

结论

在v18中,不再有三种模式,而是以「是否使用并发特性」作为「是否开启并发更新」的依据。

具体来说,在v18中统一使用ReactDOM.createRoot创建应用。

当不使用并发特性时,表现如情况3。使用并发特性后,表现如情况4。

React18稳定版最快明年一月底到来,你还学的动吗?

参考资料

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

[2]Demo地址: https://codesandbox.io/s/react-concurrent-mode-demo-forked-z7r0j?file=/src/index.js

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-11-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 魔术师卡颂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • React有多少种架构?
  • 理想与现实的差距
  • 渐进升级第一步
  • 渐进升级第二步
  • 最新的渐进升级策略
    • 原因一
      • 原因二
      • 结论
        • 参考资料
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档