You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
importReactfrom"react";importReactDOMfrom"react-dom";constUser=React.lazy(()=>import("./User"));// 此处亦可以不使用 React.lazy(),直接使用以下 import 方式引入也可以// import User from "./User"constApp=()=>{return(<React.SuspenseListrevealOrder="forwards"tail="collapsed"><React.Suspensefallback={<div>Loading...</div>}><Userid={1}/></React.Suspense><React.Suspensefallback={<div>Loading...</div>}><Userid={3}/></React.Suspense><React.Suspensefallback={<div>Loading...</div>}><Userid={5}/></React.Suspense></React.SuspenseList>);};ReactDOM.createRoot(document.getElementById("root")).render(<App/>);
本文已收录在 Github: https://github.com/beichensky/Blog 中,欢迎 Star,欢迎 Follow!
前言
本文介绍了 React 18 版本中
Suspense
组件和新增SuspenseList
组件的使用以及相关属性的用法。并且和 18 之前的版本做了对比,介绍了新特性的一些优势。一、回顾 Suspense 用法
早在 React 16 版本,就可以使用
React.lazy
配合Suspense
来进行代码拆分,我们来回顾一下之前的用法。在编写
User
组件,在User
组件中进行网络请求,获取数据User.jsx
在 App 组件中通过
React.lazy
的方式加载User
组件(使用时需要用Suspense
组件包裹起来哦)App.jsx
效果图:
此时,可以看到 User 组件在加载出来之前会
loading
一下,虽然进行了代码拆分,但还是有两个美中不足的地方需要在
User
组件中进行一些列的操作:定义state
,effect
中发请求,然后修改state
,触发render
虽然看到
loading
展示了出来,但是仅仅只是组件加载完成,内部的请求以及用户想要看到的真实数据还没有处理完成二、Suspense 的实现原理
内部流程
Suspense
让子组件在渲染之前进行等待,并在等待时显示 fallback 的内容Suspense
内的组件子树比组件树的其他部分拥有更低的优先级执行流程
在
render
函数中可以使用异步请求数据react
会从我们的缓存中读取如果缓存命中,直接进行
render
如果没有缓存,会抛出一个
promise
异常当
promise
完成后,react
会重新进行render
,把数据展示出来完全同步写法,没有任何异步
callback
简易版代码实现
子组件没有加载完成时,会抛出一个
promise
异常监听
promise
,状态变更后,更新state
,触发组件更新,重新渲染子组件展示子组件内容
三、新版 User 组件编写方式
针对上面我们说的两个问题,来修改一下我们的
User
组件多希望
User
组件能这样写,省去了很多冗余的代码,并且能够在请求完成之前统一展示fallback
但是我们又不能直接使用
async
、await
去编写组件。这时候怎么办呢?结合上面我们讲述的
Suspense
实现原理,那我们可以封装一层promise
,请求中,我们将promise
作为异常抛出,请求完成展示结果。wrapPromise
函数的含义:接受一个
promise
作为参数定义了
promise
状态和结果返回一个包含
read
方法的对象调用
read
方法时,会根据promise
当前的状态去判断抛出异常还是返回结果。使用
wrapPromise
重新改写一下User
组件这时候可以看到界面首先展示
loading
,请求结束后,直接将数据展示出来。不需要编写副作用代码,也不需要在组件内进行loading
的判断。四、SuspenseList
上面我们讲述了
Suspense
的用法,那如果有多个Suspense
同时存在时,我们想控制他们的展示顺序以及展示方式,应该怎么做呢?React 中也提供了一个新的组件:
SuspenseList
SuspenseList 属性
SuspenseList
组件接受三个属性revealOrder
: 子Suspense
的加载顺序forwards: 从前向后展示,无论请求的速度快慢都会等前面的先展示
Backwards: 从后向前展示,无论请求的速度快慢都会等后面的先展示
together: 所有的 Suspense 都准备好之后同时显示
tail: 指定如何显示
SuspenseList
中未准备好的Suspense
不设置:默认加载所有 Suspense 对应的 fallback
collapsed:仅展示列表中下一个 Suspense 的 fallback
hidden: 未准备好的项目不限时任何信息
children: 子元素
子元素可以是任意 React 元素
当子元素中包含非
Suspense
组件时,且未设置tail
属性,那么此时所有的Suspense
元素必定是同时加载,设置revealOrder
属性也无效。当设置tail
属性后,无论是collapsed
还是hidden
,revealOrder
属性即可生效子元素中多个
Suspense
不会相互阻塞SuspenseList 使用
User
组件App
组件使用 SuspenseList 后效果图
相关链接
wrapPromise
方法取自 Dan Abramov 的 frosty-hermann-bztrp后记
好了,关于 React 中 Suspense 以及 SuspenseList 组件的用法,就已经介绍完了,在 SuspenseList 使用章节,所有的代码均已贴出来了。有疑惑的地方可以说出来一起进行讨论。
文中有写的不对或不严谨的地方,欢迎大家能提出宝贵的意见,十分感谢。
如果喜欢或者有所帮助,欢迎 Star。
The text was updated successfully, but these errors were encountered: