渲染优化
引言
@autostorejs/react是一个基于Proxy的响应式状态系统,其提供了useReactive和signal机制来实现更细粒度的渲染。
以下我们就如何优化React渲染,举了几个例子。
Context
我们先看一个传统的Context的渲染例子。
loading
从上面的例子可看到,当更新Context.age时,所有的子组件不管是否有使用Age均会重新渲染,而这是不必要的,因为子组件并没有使用到Context的数据,为此我们一般需要使用React.memo或一些第三方库来进行优化渲染。
提示
最大的问题在于,当更新根Context时,所有的子组件都会重新渲染,这是不必要的,因为子组件并没有使用到根Context的数据。我们希望能实现更细粒度的渲染,只有当子组件使用到的数据发生变化时,才会重新渲染。
useReactive
为了优化渲染逻辑,一般我们会使用React.memo来进行优化渲染。
loading
- 在上例中,当更新
Age时,仅根组件会重新渲染,而FirstName和LastName不会重新渲染,因为它们并没有使用到Age。 - 当在根组件中更新
FirstName时,仅FirstName会重新渲染。而LastName组件中没有FirstName,所以不会重新渲染。
提示
在大型React应用,面对复杂的状态变化,如何决定何时使用React.memo是一个很大的心智问题,也是最容易搞坑里的,这也是为什么React官方要推Compiler的原因
信号组件
而更好的办法就是最近比较流行的signal机制,signal机制可以将渲染颗粒度限定在组件范围,只有使用到数据的组件才会重新渲染。
基于Signal,渲染颗粒度可以是组件中的一个片段或ReactNode,更加精细,更加高效。
了解更多关于Signal的内容,可以阅读深入解析:React中的信号组件与细粒度更新
loading
- 在上例中,提供了更细粒度的更新,当状态变化时,仅
$(....)内部会重新渲染,而其他部分不会重新渲染。再也不需要React.memo了。 - 关于
Signal的更多用法,可以参考信号组件
提示
本文档演示中使用的色块组件ColorBlock在最右侧会显示组件的渲染次数,每渲染一次+1,方便观察组件的渲染更新情况。