The React Suspense component was first launched with React 16.6, and it has been further expanded with the release of React 18. Initially, React Suspense could only be used for code splitting with the React.lazy API. However, the React team has worked to improve Suspense’s capabilities, with the goal of making it work with data fetching in the future as well.
This shows why it is critical for React developers to understand how to work with React Suspense. This article discusses how to improve the code quality of web loaders by using Suspense in React 18.
1. Understanding React Suspense
Let’s start with how the component works with the lazy loading components.
When using the Suspense component, you must provide a fallback option. It accepts any React components or even a string to render while the lazy component is loading.
Take a look at the example below, which uses the Suspense wrapper to display a typical loader until the is ready.
import { lazy, Suspense } from 'react';
const LazyLoadComponent = lazy(() => import('./LazyLoadComponent'));
function MyComponent() {
return (
<Suspense fallback={<Loader />}>
<div>
<LazyLoadComponent />
</div>
</Suspense>
);
}
Within a single Suspense component, you can place one or more lazy components. You can also place multiple Suspense wrappers, and the one closest to a lazy component will be used.
<Suspense fallback={<MainLoader />}>
<Suspense fallback={<SideContentLoader />}>
<SideContent />
</Suspense>
<MainContent />
<Suspense fallback={<CommentsLoader />}>
<Comments />
</Suspense>
</Suspense>
You can also look at the code sandbox implementation of the above example to gain a better understanding of it.
Now, let’s take a look at the enhancements Suspense received in React 18.
2. Improvements for Suspense in React 18
Server-Side Rendering
Suspense is no longer limited to lazy components, thanks to React 18’s new concurrent rendering. You can now use Suspense to wrap any React component in your component tree and specify their loading state declaratively.
In both of the previous examples, you can replace the lazy components with normal components and Suspense will still function according to the same principles.
This greatly simplifies the process of adding loaders to your web app.
startTransition API
Another new feature of React 18 is the startTransition API, and it can be used to improve the use of Suspense.
When switching between tab views, it would be undesirable if the previously displayed loader was shown to the user again after the user had seen the content. In such cases, useTransition() Hook and the startTransition() function can be used to display the old UI until the new UI is ready to be displayed. The startTransition API can help you avoid unexpected fallbacks by marking non-urgent UI updates as transitions.
Example: https://codesandbox.io/s/react18-set-transition-suspense-demo-t8yt0
Here, if the useTransition() was not used, then the loader will appear each time the user switches between the tabs.
3. Why use React Suspense?
Without Suspense, we have to access the state and write a bunch more code to display loaders in React. The code piece below demonstrates how to display loaders without using Suspense.
function MyComponent() {
const [isLoading, setIsLoading] = useState(false);
return (
<div>
{isLoading ? (
<Loader />
) : (
<AppContent />
)}
</div>
);
}
At first glance, the change from isLoading ? to may not appear to be significant, but in large projects, it will make a significant difference. When React improves Suspense to work with data fetching as well, things will get even better.
Suspense has been added to React 18 for data fetching in the frameworks Relay, Next.js, Hydrogen, and Remix. Although Suspense allows for ad hoc data fetching, the React team does not recommend it as a general practice just yet.
Conclusion
This article covered the Suspense component, new improvements to Suspense in React 18, and why you should use Suspense. I hope you now have a clear grasp of the Suspense component. So, start using Suspense and improve the quality of your React code.
Reference: