TABLE OF CONTENTS
Suspense refers to React's new ability to “suspend” rendering while components are waiting for something and display a loading indicator. React suspense allows you to write cleaner React components that are performant and are easy to maintain. This article explains what React Suspense is and How it Works.
What is Data Fetching and React Suspense?
Data fetching is a very common frontend task, right? Whether you are making an API call or loading a large array of data from a file or database, you'll need a mechanism that will allow you to effectively load the data into your frontend application.
Well, depending on the size of the data and the data fetching mechanism, this can come with some setbacks, especially from a UX perspective. Having users waiting for a longer time than expected without letting them know what is happening can lead to double-clicks, frustration, and users saying “it‘s not working”.
But React Suspense, a feature that was released as part of React 16.6, changes this approach and makes it easier to build a more friendly user interface without breaking a sweat.
So, what is React Suspense actually?
According to Reactjs.org, Suspense refers to React's new ability to “suspend” rendering while components are waiting for something and display a loading indicator.
That’s pretty straightforward, right? You’ll find this feature handy when fetching huge amounts of data or when the user's internet connection is slow, etc.
Why is React Suspense useful?
React suspense allows you to write cleaner React components that are performant and are easy to maintain — React Suspense Leverages React Lazy which mostly helps with performance improvement by delaying the loading of an object, API call response, etc until it is needed. The best part is that the user’s experience will be improved as well as It will reduce the chances of double-clicking.
What does it look like to perform data fetching operations without React Suspense? Let’s see an example of how you’d wait for a data fetching operation without React suspense.
Data fetching without React Suspense
First off, let's set up a basic React App so you can really follow up.
Setup ReactJS with Vite by running the command below on your Terminal:
Follow the instruction on the Vite CLI tool and choose React as the development framework as shown below.
A basic ReactJS app template will be created for us to get started with. The directory structure should look like so:
Run `npm install` to install the React dependencies.
Now, we are good to go.
Let’s open the `App.jsx` file and fetch users from a placeholder API.
Our first component will display a single user when fetched from the API.
And we’ll have another component that will implement the data fetching and display the individual user components.
In the above component, we’ve used the `setTimeOut` function to simulate a delay in the data fetching mechanism.
Assuming we need to fetch data from 3 different API endpoints simulated in the above code as users1, users2, and users3 and we can’t really tell how long it will take for those endpoints to return a response, we’ve set the time it takes to return a response to be 2, 4, and 6 seconds respectively for each of the requests (fetch 1, fetch 2, and fetch 3).
And we’ve also got 3 statuses to monitor the state of the data fetching process, status1, status2, and status3.
So, for each of the data coming from the API, we’ll check its status and display a loading indicator to let the user know that something is coming; otherwise, we’ll return the data from the API response.
As you can see, there are a lot of code duplication and conditionals. This is where `React.Suspense` comes in handy — if you want to write more readable ReactJS code with less duplication.
With React.Suspense, we will only need to wrap the User component in a Suspense component and specify a `fallback` — this fallback could be a text saying loading, an image, or even another component.
So, in case your network is slow or it’s taking time to load the components, the Suspense fallback prop will be rendered. There will be no need to create multiple statuses or multiple state objects to watch the progress of your data fetching.
How do we really use React Suspense?
How to use React Suspense: Data fetching with React Suspense
It’s important to note that React Suspense is not a data fetching API like Fetch or Axios. Rather, it lets you use these tools effectively without hurting your app’s performance or annoying your users.
Let’s convert our previous component to use React Suspense. You’ll need to use React Lazy to accomplish this task since React Lazy can allow you to render a dynamic import as a regular component.
So, you can wrap multiple React Lazy components in one React Suspense component like so:
React Suspense will ensure that all the React Lazy components which, of course, return a promise have been fulfilled before rendering the components.
However, if you want to render the components individually, you can wrap the React Lazy components in their individual React Suspense components like so:
Here is a basic component code to illustrate how you’ll use React Lazy with React Suspense to achieve the desired result — I’ve attached the completed code at the end of this article. Again, we’ll use setTimeout to simulate a longer loading time. However, you’ll not need to use this approach in a real-life application.
How React Suspense Actually Works
Notice how we imported React Lazy as a promise? Of course, React Suspense expects the child components to be resolved promises, if it isn’t resolved yet —- that means it’s still in a pending state, your fallback component— the one that says “Loading” will be rendered.
Right now, you are able to use React Suspense with React Lazy for code-splitting —- by wrapping a dynamic import in a call to `React.lazy()` which allows you to import and render only the bundle you need. In the future, when React Suspense for data fetching is released (currently experimental), it’ll allow you to cache resources and re-use them if they don’t change instead of making a new API call. When the Suspense API is fully rolled out, other Suspense-related features like SuspenseList, UseTransition, useDeferredValue will follow.
I’m really fascinated about how SuspenseList will work, let’s take a sneak pick.
React Suspense List
React SuspenseList allows you to add an ordered sequence to how your components will be rendered. So, instead of just rendering any component that is ready with the required data, you might want to render the component that has the user’s personal information first, their job, and so on.
You’ll only need to wrap all the Suspense components in the SuspenseList component in the order you want it and include the ordering prop `revealOrder` (`forwards`, `backwards`, `together` ) and a tail prop with any of the following settings (collapsed, hidden).
Forwards and backwards will reveal the components from top to bottom or bottom to top respectively. However, the together prop will reveal the components only when all of them are ready to be rendered.
Handling errors with React Suspense
Handling React Suspense errors is like handling errors for any other React component.
You'll need to create an Error Boundary and wrap it around your Suspense component. Let’s see an example.
The above component is an ErrorBoundary component. It’s like a try-catch block that catches all the errors and returns a friendly error message without breaking the entire application.
This is how you’ll use it in your component.
You can also use this Error Boundary npm package to catch your errors. You can pass a fallback UI to an Error Boundary so that you can return a specific message or UI for that error.
React Suspense is a useful toolkit for frontend development. The best part is that it’s easy to implement and the benefit is outstanding for both your users and your dev team. It’s definitely worth trying in case you haven’t used it before.