通过渲染调优章节 Suspense 的介绍,我们知道 Suspense 异步组件的原理本质上是让组件先挂起来,等到请求数据之后,再直接渲染已经注入数据的组件。
但是如果存在多个 Suspense 异步组件,并且想要控制这些组件的展示顺序,那么此时通过 Suspense 很难满足需求。
比如存在 C、D、E 三个需要 Suspense 挂起的异步组件,因为受到数据加载时间和展示优先级的影响,期望 C->D->E 的展示顺序,这个时候传统的 Suspense 解决不了问题。
React 18 提供了一个实验性组件 —— SuspenseList ,SuspenseList 通过编排向用户显示这些组件的顺序,来帮助协调许多可以挂起的组件。
注意:SuspenseList 截至目前仍为实验性 API(
@experimentalnpm 标签),未进入稳定版本。React 团队已转向其他方案(如usehook + 服务端组件),生产环境中不建议依赖此 API。
虽然没有正式出现,不过我们来看一下如何使用 SuspenseList 处理组件展示顺序。我们可以理解成 SuspenseList 可以管理一组 Suspense ,并且可以控制 Suspense 的展示顺序。
SuspenseList 接受两个 props:
第一个就是 revealOrder,这个属性表示了 SuspenseList 子组件应该显示的顺序。属性值有三个:
比如看一下官方的例子:
<SuspenseList revealOrder="forwards">
<Suspense fallback={'加载中...'}>
<CompA />
</Suspense>
<Suspense fallback={'加载中...'}>
<CompB />
</Suspense>
<Suspense fallback={'加载中...'}>
<CompC />
</Suspense>
...
</SuspenseList>如上当 revealOrder 属性设置成 forwards 之后,异步组件会按照 CompA -> CompB -> CompC 顺序展示。
另外一个属性就是 tail,这个属性决定了如何显示 SuspenseList 中未加载的组件。
比如我们把如上案例中 SuspenseList 加入 tail="collapsed" 之后,只会显示第一个未就绪的 CompA 的 fallback,CompB、CompC 的 fallback 不再展示。
在 React v18 中 对服务端渲染 SSR 增加了流式渲染的特性 New Suspense SSR Architecture in React 18 , 那么这个特性是什么呢?我们来看一下:
刚开始的时候,因为服务端渲染,只会渲染 html 结构,此时还没注入 js 逻辑,所以我们把它用灰色不能交互的模块表示,灰色的模块不能做用户交互,比如点击事件之类的。
js 加载之后,此时的模块可以正常交互,所以用绿色的模块展示,我们可以把视图注入 js 逻辑的过程叫做 hydrate (注水)。
但是如果其中一个模块,服务端请求数据,数据量比较大,耗费时间长,我们不期望在服务端完全形成 html 之后在渲染,那么 React 18 给了一个新的可能性。可以使用 Suspense 包装页面的一部分,然后让这一部分的内容先挂起。
接下来会通过 script 加载 js 的方式 流式注入 html 代码的片段,来补充整个页面。接下来的流程如下所示:
在这个原理基础之上, React 个特性叫 Selective Hydration,可以根据用户交互改变 hydrate 的顺序。
比如有两个模块都是通过 Suspense 挂起的,当两个模块发生交互逻辑时,会根据交互来选择性地改变 hydrate 的顺序。
我们来看一下 Selective Hydration 在 SSR 上的流程:
通过本章节的学习,我们明白了以下内容:
Suspense 的新特性 SuspenseList 能够让多个 Suspense 编排展示更加灵活(截至目前仍为实验性 API,生产环境不建议依赖)。
在 React v18 新特性中,Suspense 能够让 React SSR 流式渲染 html 片段,并且根据用户行为,自主的选择 hydrate 的顺序。