Skip to content

实现Suspense

第22课 实现Suspense

本节课代码地址(请参考课程获取) 本节课的目标:了解·Suspense·的实现原理及后续扩展思路,而不是「实现全功能的 Suspense」 在React 中,与Suspense 相关的特性:

  1. Lazy 组件
2. transition fallback (比如 useTransition )
  1. use
  2. Offscreen 组件
5. Selective Hydration
  1. RSC (React Server Component)

Suspense的架构

Demo:

jsx
<Suspense fallback={<div>loading...</div>}>

<Cpn/>

</Suspense>

正常状态,<Suspense/> 渲染子孙组件 挂起状态,<Suspense/> 渲染fallback 其中,造成挂起状态的原因有很多,比如: <Cpn/> 或其子孙是懒加载组件(Lazy文档) <Cpn/> 或其子孙触发并发更新(useTransition<Cpn/> 或其子孙是Selective Hydration<Cpn/> 或其子孙使用use 请求数据 总结:凡是涉及 「初始状态」 -> 「中间状态」 -> 「结束状态」 的流程,都可以纳入

jsx
<Suspense/>

Suspense实现思路

思路一:只有一个child

缺点:

  1. 无法保存children 对应状态
  2. 切换后children 对应DOM 需要完全销毁

思路二:有两个child

beginWork 时有选择的返回其中一个child ,但另一个child 也存在于fiber 树中: Offscreen 可以用来实现Keep-Alive 对于下面的代码,一共存在4种流程:

jsx
<Suspense fallback={<div>loading...</div>}>

<Cpn/>

</Suspense>
  1. mount 时正常流程(对应方法mountSuspensePrimaryChildren
  2. update 时正常流程(对应方法updateSuspensePrimaryChildren
  3. mount 时挂起流程(对应方法mountSuspenseFallbackChildren
  4. update 时挂起流程(对应方法updateSuspenseFallbackChildren

Suspense工作流程

  1. beginWork 时进入上述任一流程
2. completeWork 时对比current Offscreen mode 与wip Offscreen mode ,如果发

现下述情况,则标记Visibility effectTag

mode 从hidden 变为visible
mode``从visible 变为hidden
current === null  && hidden
3. commitWork 时处理Visibility effectTag

处理Visibility effectTag 时需要找到所有子树顶层Host 节点:

jsx
function Cpn() {

return (

<p>123</p>

)

}

情况1,一个host节点:

jsx
<Suspense fallback={<div>loading...</div>}>

<Cpn/>

</Suspense>

情况2,多个host节点:

jsx
<Suspense fallback={<div>loading...</div>}>

<Cpn/>

<div>

<p>你好</p>

</div>

</Suspense>

如何触发Suspense?

思考一个问题:上述4种流程是在「不同更新触发的render流程」中出现的么? 对于demo中的例子,经历了:

  1. 正常流程对应render 阶段
  2. 遇到use ,进入挂起流程
  3. 进入挂起流程对应render 阶段
  4. 进入挂起流程对应commit 阶段(渲染loading)
  5. 请求返回后,进入正常流程对应render 阶段
  6. 进入正常流程对应commit 阶段(渲染Cpn) Suspense 涉及到render 阶段的一个新流程 —— unwind 流程 总结学到的三种流程: beginWork :往下深度优先遍历 completeWork :往上深度优先遍历 unwind :往上遍历祖辈 Demo中的unwind 流程: 数据返回后的正常流程: 涉及到unwind 流程的特性:
Suspense
Error Boundary

实现use hook与unwind流程

use 可以接收的数据类型:

Thenable
ReactContext

unwind 流程如何进行到最近的Suspense

用心学习,用代码说话 💻