现有React架构无法解决的问题

开发 前端
前端框架普遍遵循「单向数据流」。既然是单向数据流,那就存在跨组件传递props的情况。

大家好,我卡颂。

虽然主流前端框架都遵循:

  • 状态驱动视图
  • 单向数据流

理论上并不存在某一框架可以实现,其他框架无法实现的特性。

但是,确实存在某些框架(比如Vue、Qwik)可以,但React无法解决的问题。这就是「极致性能优化」问题。

本文来聊聊React性能优化无法解决的问题。

props下钻

前端框架普遍遵循「单向数据流」。既然是单向数据流,那就存在跨组件传递props的情况。

这种情况被称为「props下钻」(props drilling)。

比如,在下面的应用中:

  • <App/>组件定义状态number。
  • <AGrandChild/>组件消费number。
  • <BGrandChild/>组件包含改变number的方法setNumber。

这种将props(这里的number)层层向下传递(从<App/>到<AGrandChild/>)的情况,就是「props下钻」:

图片

「props下钻」是非常常见的场景。面对这种场景,React的性能怎么样呢?

props下钻的性能

思考一个问题:对于上面的例子,当调用<BGrandChild/>中的setNumber方法改变number后,哪些组件会重新render?

答案是:<App/>的所有子孙组件都会重新render。

这显然与我们的预期不符。

直觉上看,起码<B/>、<C/>及其子孙组件不应该render,毕竟他们都不依赖number。

为了达到这个目标,我们需要使用React.memo包裹<B/>、<C/>,这显然会带来额外的心智负担。

为了减少开发者的心智负担,在2021年的React Conf,黄玄带来了React Forget编译器,他能够为现有业务代码生成等效于useMemo、useCallback的代码。

也就是说,理想情况下,他能够代替开发者完成React项目的性能优化。

但是,回到我们的例子会发现 —— 即使做了性能优化,也无法达到最理想的状态。

整个应用中只有<AGrandChild/>消费了number,理想情况下,当number变化后,应该只有<AGrandChild/>需要render。

但在React中,即使性能优化后,<App/>与<AGrandChild/>沿途的组件也会render:

图片

而默认情况下(不优化性能),整个应用都会render:

图片

造成这一问题的原因在于 —— 对于任一状态,React不知道哪些组件依赖他。

在「props下钻」场景下,虽然<App/>与<AGrandChild/>沿途的组件仅仅是传递number(而不是依赖他),但React无从得知。

那如果明确的表示依赖关系,是不是能解决这个问题呢?

比如,我们不使用props,而是在<App/>定义context number,再在<AGrandChild/>中消费number:

图片

遗憾的是,在React中context的实现也是依赖组件树的遍历(可以理解为React内部实现的「props下钻」),所以并不能解决这个问题。

Signal

解决这个问题的关键在于 —— 明确状态与组件的依赖关系。

这种建立组件与状态之间依赖关系的技术叫「响应式更新」(熟悉Vue的同学应该不陌生),也有些框架称其为Signal。

应用这种技术的框架(比如Vue、Qwik),当状态变化,只有依赖该状态的组件会更新。

总结

正是由于React底层架构的原因,导致应用的性能优化无法达到最理想的状态。

这同时也是为什么React中有很多性能优化API(比如React.memo、useMemo、 useCallback...),而采用Signal技术的框架没有这些性能优化API的原因。

责任编辑:姜华 来源: 魔术师卡颂
相关推荐

2013-12-05 09:45:04

HadoopHadoop架构图

2020-06-23 08:37:11

物联网工业技术

2022-06-08 08:01:20

useEffect数组函数

2021-07-29 07:55:20

React Fiber架构引擎

2009-08-19 22:21:16

无法安装VMWARE

2011-04-29 14:00:23

MSN故障

2010-08-31 13:56:38

PHP5多线程

2010-08-03 09:41:14

GroupSQL Server

2009-12-31 14:50:12

ADSL网络无法解析

2010-08-06 09:42:39

2011-07-06 14:09:40

ASP

2021-01-29 14:31:42

Github 解决方案网站

2010-08-25 13:06:53

IP地址故障

2010-06-12 09:02:12

Ubuntu Grub

2022-12-30 16:19:48

鸿蒙开发工具

2024-11-04 13:17:12

2015-01-22 09:18:30

2021-02-19 07:40:25

React前端React-Query

2020-05-15 22:47:22

电脑开机运行

2010-01-05 16:09:37

交换机无法ping通
点赞
收藏

51CTO技术栈公众号