Building highly performant and scalable applications remains the goal of all developers. It’s not ideal to let users wait indefinitely for a particular node of the Document Object Model (DOM) to render. React Suspense allows you to conditionally render a particular fallback UI or node while waiting for a particular component to load. It tackles the drawback of seeing a blank screen while a component is yet to be mounted on the DOM.
In this article, you will learn about React Suspense, its benefits, common use cases, the working principle, and how it improves the performance of your React applications.
What is React Suspense?
React Suspense is a built-in Reactjs framework component that allows you to render a separate component (typically a fallback UI) while waiting for the actual component to render. It makes use of the Suspense API by wrapping the component to be rendered in the <Suspense />
component.
Benefits of React Suspense
- Improved User Experience: One key benefit of React Suspense is that it improves the overall look and feel of your application. Rather than displaying a blank screen, it allows users to be constantly aware of the current state of the application as if to say “Hey, hold on a sec while I get this content out.”
- Improved Performance: It improves performance in an application by enhancing React Suspense data fetching and code splitting. It allows developers to simply implement loading states by using the API rather than manually implement states using hooks or ternary operators.
- Better Error Handling: It provides a better error-handling method than the traditional approach by making use of error boundaries.
Use Cases of React Suspense
The React Suspense feature is particularly useful in the following areas:
- It allows you to render a dynamic import as a regular component using
React.lazy
which improves the overall performance of your application. - It is used in data fetching to optimally display content.
- It’s helpful when implementing and managing loading states for multiple components.
How Does it Work?
To make use of React Suspense in your application, you wrap the content to be rendered in the <Suspense />
component and also pass your Suspense fallback component (the component you want to use as a placeholder just before the actual component renders) as a prop using the fallback
property. The first step will be to import Suspense from React as shown below:
import { Suspense } from 'react'
Here is the basic syntax of using React suspense in your application:
<Suspense fallback={<FallbackComponent />}>
<PiecesComponent />
</Suspense>
Here, we actually want to render the <PiecesComponent/>
, but if the component fails to render or takes a while longer, we want to render a <FallbackComponent/>
which could just contain a simple “Loading…” text or some image content such as a loading gif.
Data Fetching using React Suspense
As you would rightly guess, an area where React Suspense comes in handy is fetching data from an API. An application is very likely to run into errors when fetching data from a particular server so we must carefully manage the states and how it progresses.
Consider a scenario where a server we’re fetching data from a server that is down or unresponsive at that moment, we have to create a separate fallback component that handles the event of the server being down. Let’s see an example below where we try to fetch data from some mock API:
import { Suspense } from 'react'
import mockData from ".mockData.js";
const response = mockData("data.json");
<Suspense fallback={<h1>Please wait while the data is being fetched…</h1>}>
<Users />
</Suspense>;
function PiecesComponent() {
const data = response.result();
return (
<div>
{data.map(({ id, name }) => {
<h1 key={id}>{name}</h1>;
})}
</div>
);
}
This approach is more straightforward than traditionally fetching data, defining multiple variables, and implementing logic to manage the loading states. Here, we simply pass in the mock data into a variable and then map through the result. While the data is being fetched, we display a message on the screen that says “Please wait while the data is being fetched…”
Lazy Loading
The expected behavior of a webpage, when it mounts on the DOM, is to display all the components needed for that particular page. However, with lazy loading, it does not behave in that manner. Lazy loading is a content rendering technique that renders components on a webpage only when the browser or the user needs it.
Lazy loading is used to improve the performance and initial load time of an application by preventing certain components and resources(most times, images) from loading when it’s not needed. It basically tells the component “Hey, just hold on till you’re requested, okay?”
The React platform allows us to lazy load components using the built-in lazy()
function. The lazy function, together with React Suspense, allows you to import a component we want to lazy load while having a fallback component or content in place. Let’s see how it works:
import { lazy } from "react";
const PiecesComponent = lazy(() => import("./PiecesComponent.jsx"));
function App() {
return (
<Suspense fallback={<h1>Loading...</h1>}>
<PiecesComponent />
</Suspense>
);
Here, I want to render the PiecesComponent
to the DOM but only when it’s needed. So we import the PiecesComponent
and wrap it using the lazy
function so it gets rendered on the DOM only when it’s requested. We also implement a fallback text that says “Loading…”.
Handling Errors using Error Boundaries in React Suspense
Error boundaries are components in React that help to catch errors and display a fallback UI instead of logging those errors to be displayed in the DOM. It provides the flexibility of rendering a separate component if it catches an error. An error boundary can be defined in React using class components as shown below:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
logError(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Oops! Something went wrong</h1>;
}
return this.props.children;
}
}
This code snippet creates an error boundary that catches an error (if there are any) and displays a text that says “Oops! Something went wrong”. We can then proceed to use this error boundary in our application as shown below:
<ErrorBoundary>
<Suspense fallback={<h1>Loading...</h1>}>
<MyComponent />
</Suspense>
</ErrorBoundary>
And all set! We have implemented an error boundary that renders different content to the DOM if an error is caught.
Conclusion
In this tutorial, you have learned about React Suspense, its benefits, use cases, how to useSuspense React, data fetching, lazy loading, and how to implement error boundaries. You may want to learn about React js by example, in which case you can read about the recent features of React 18 by following our comprehensive guide or further broaden your scope by learning how to implement React infinite scrolling using React Query, an article on content rendering in React. Happy coding!