首先要提一下,Suspense 是 React 16.6 之后正式发布的。它是生产就绪的,并且不仅限于代码拆分。任何异步代码都可以与之集成。
关于好处,请考虑以下用例:
- 我们有几个组件都在其中使用了一些异步代码(例如获取远程资源)
- 我们需要显示一个加载指示器,直到所有组件完成它们的工作
- 如果某些组件未能履行职责,我们需要显示相应的错误
老办法
这样做的好方法是:
- 创建一个包装器组件以显示加载指示器和错误消息
- 跟踪每个组件内部的加载和错误状态,并将状态更改通知包装器组件
这一切看起来都是不必要的、难以更改的样板吗?是的,确实如此)。
新方式
React 引入了 Suspense 组件和 Error Boundaries 以消除此样板文件并以声明方式描述所需的行为。
看看这个:
<Exception fallback="An error has occured">
<Suspense fallback="Loading...">
<OurComponent1 />
<OurComponent2 />
<OurComponent3 />
</Suspense>
</Exception>
示例
假设我们想从远程资源中获取用户的数据。
const fetchUsers = async () => {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await response.json();
console.log("Users data", users);
return users;
};
我将使用makeSuspendableHook 将我们的异步获取集成到<Suspense> 和错误边界内。
const useUsers = makeSuspendableHook(fetchUsers());
在我们的组件中,我们应该关心的只是实际数据及其表示。
const Users = () => {
const users = useUsers();
return (
<div>
List fetched users:
<ul>
{users.map(({ name }) => (
<li>{name}</li>
))}
</ul>
</div>
);
}
最后,我将使用Exception 作为错误边界实现将所有内容拼接在一起。
export default () => (
<Exception fallback="An error has occurred">
<Suspense fallback="Waiting...">
<Users />
</Suspense>
</Exception>
);
Play with web example at codesandbox.io
Play with native example at snack.expo.io