First of all, I would like to mention that Suspense is officially released since React 16.6. It is production-ready and it is not limited only to code-splitting. Any asynchronous code can be integrated with it.
As of the benefits, consider the following use-case:
- We have several components that all use some asynchronous code inside them (like fetching remote resources)
- We need to display a loading indicator until all components are finished doing their job
- We need to display an appropriate error if some of the components have failed to do their duty
Old way
The good old way of doing this would be:
- Create a wrapper component for showing loading indicator and error messages
- Keep track of loading and error state inside of each component and inform the wrapper component of state changes
Does this all look like unnecessary, hard to change boilerplate? Yes, it does).
New way
React introduced the Suspense component and Error Boundaries to eliminate this boilerplate and to declaratively describe the desired behavior.
Check this out:
<Exception fallback="An error has occured">
<Suspense fallback="Loading...">
<OurComponent1 />
<OurComponent2 />
<OurComponent3 />
</Suspense>
</Exception>
Example
Suppose we want to fetch users' data from the remote resource.
const fetchUsers = async () => {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await response.json();
console.log("Users data", users);
return users;
};
I will use makeSuspendableHook to integrate our asynchronous fetch within <Suspense>
and Error boundary.
const useUsers = makeSuspendableHook(fetchUsers());
In our component, all we should care about is the actual data and its representation.
const Users = () => {
const users = useUsers();
return (
<div>
List fetched users:
<ul>
{users.map(({ name }) => (
<li>{name}</li>
))}
</ul>
</div>
);
}
Finally, I will use Exception as an Error Boundary implementation to stitch everything together.
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