Suspense API
Suspense 主要有两大用途:
1:动态加载组件 (但这并不是一个react 18的新特性)
2: 等待数据异步加载
想要实现这两种功能,需要满足对应的条件,可以在官方文档中清楚的看到:
从文档中可以看到只有Suspense-enabled data sources才可以使用这个标签,
那么在Data fetching ,也就是等待数据异步加载的过程中,则需要对数据进行特殊的处理,现有的Relay框架,Next框架则已经支持这种格式,可以直接使用Suspense,这也是suspense 处于一个实验性阶段的原因之一,希望越来越多的框架可以支持suspense~。
将Promise 转化为 Suspense支持的数据机构
既然要使用suspense ,那么就要把数据转化为suspense支持的格式,具体我们可以通过实现一个 wrapPromise 函数来进行处理:
这个函数需要完成:
- 接收一个Promise 作为参数
- 当 promise resolve 时,返回resolve 的结果
- 当promise reject时, 抛出 reject 的结果
- 当promise 还处于pending时,抛出此时的promise对象
- 向外暴露一个read 方法,读取promise 的结果
接下来使用代码来实现:
function wrapPromise (promise: Promise<any>) {let status = 'pending';let result: any;const suspender = promise.then( (resolve) => {status = 'success';result = resolve;}, (err) => {status = 'error';result = err}) return {read(){ // 暴露一个read方法if( status === 'pending'){throw suspender} else if ( status === 'error'){throw result} else if ( status === 'success'){return result}}}
}
有了这个函数之后,就可以对得到的promise对象进行处理
for example:
export default function fetchData(url: string){const promiseData = axios.get(url).then( data => data.data)return wrapPromise(promiseData)
}
请求数据并展示在页面中
// DogShow.tsximport React from "react"
import fetchData from "../fetchData/fetchData"const data = fetchData('https://dog.ceo/api/breeds/image/random')const ShowDog: React.FC = () => {const style = {height: 300,width : 300}const dogData = data.read()return (<> <img src={dogData.message} style={style}/></>)
}export default ShowDog
// App.tsxfunction App() {return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><Suspense fallback={<><h1>正在加载....</h1></>}><ShowDog></ShowDog></Suspense></header></div>);
}export default App;
Suspense 强制接收一个 fallback,这里面可以是发送请求时要加载的组件
数据正在请求时:
请求完成之后则会替换成相应的结果
以上,
文中如果有任何问题欢迎大家交流与讨论~
有关suspense 其他内容可以查阅官方文档:
https://react.docschina.org/reference/react/Suspense