技术

React渲染: legacy和concurrent

React不同渲染模式,以及渲染模式对第三方组件库的影响

省流

我们项目中使用的版本为React18,该版本默认支持concurrent特性,为更好的性能,需要将处于legacy特性的代码改为concurrent特性

一般来说有三种特性

Legacy:如果项目中使用了一些旧的api,比如ReactDOM.render,那么react

Blocking:被废弃了,是一个实验性功能,应该是为了迁移React版本产生的临时产物(参考链接:github.com

Concurrent:支持React18的所有并发特性,包括自动批处理、异步可中断、支持一些异步hooks:useTransition...etc

React渲染时,什么时候是legacy,什么时候是concurrent?

如果控制台产生图下error信息,说明使用了ReactDOM.render的写法,导致回退为React17的特性,也就是legacy状态

反之,使用React18推荐的createRoot写法,那么React18默认启用的就是concurrent状态,不需要做修改

如何修改?

有两种情况:

  • 我们作为开发人员,错误使用了ReactDOM来创建节点,那么需要将ReactDOM的创建修改为creatRoot

Eg.

  • 第三方的库使用了较低版本的React,那么在使用三方库的时候,我们的项目也会出现相应的报错信息,这种情况需要升级三方库的版本

拓展

如果混合使用ReactDOM和createRoot,那么处于什么状态?

如果存在多个root,每一个root都有独立的渲染模式和调度机制,按照粒度生效

ReactDOM.render(...)   // legacy root
                       // 比如是一个自定义小组件
createRoot(...)        // concurrent root
                       // 比如是一个app组件

为什么X6的2.0能支持异步渲染

x6在react中使用需要安装react插件

X6自身的1.x版本中,使用的React版本低于18,那么React本身就不支持并发处理、不支持异步中断

所以基于react插件的x6 1.x版本,自然就不能支持异步渲染了

我们简单验证一下:

在1.x版本的x6中,package中的react依赖低于18.x

接下来看一下x6源码仓库的2.x版本

QED

备注

Legacy模式

  • 同步阻塞:渲染任务一旦开始就必须完成

  • 不可中断:无法响应更高优先级的用户交互

  • FIFO(先进先出):按顺序处理所有更新

Concurrent模式

  • 时间切片:将渲染工作分成5ms左右的小块

  • 可中断:高优先级任务可以打断低优先级渲染

  • 优先级调度:用户交互 > 动画 > 数据加载 > 普通更新