Yomi Eluwande JavaScript Developer. Wannabe Designer and Chief Procrastinator at Selar.co and Worklogs.co

React Suspense: Async Rendering in React

6 min read 1828

An Explanation of How and Why to Use React Suspense

What is React Suspense?

Suspense is a new React feature that was announced recently at the JSConf Conference in Iceland. It aims to help with handling async operations respectively in regard to CPU power and data fetching.

Suspense allows you to defer rendering part of your application tree until some condition is met (for example, data from an endpoint or a resource is loaded).

In this article, we’ll explore Suspense and see what potential impact this feature will have on the way React apps are built.

Why React Suspense?

There’s a good chance you’ve come across SPAs that make use of a loading icon as an indicator that data is being fetched. This is a common method used to ensure good UX for apps that are fetching data from external sources. All you have to do is check if the data has been successfully fetched, and if not, show a spinner.

However, this might not scale when the data fetching process becomes complicated:

  • When both the parent and child component have loading states
  • When you need a component to load only after some other (child) components have been loaded

The key module that makes Suspense work is the createFetcher function. Available on npm as the simple-cache-provider, it works as outlined below:

  • In the render() method, read a value from the cache
  • If the value is already cached, the render continues like normal
  • If the value is not already cached, the cache throws an error
  • When the promise resolves, React continues from where it stopped
import { createResource } from 'simple-cache-provider';

const someFetcher = createResource(async () => {  
  const res = await fetch(`https://api.github.com/search/users?q=yomete`);
  return await res.json();

export default someFetcher;

We create a fetcher function using createResource from the simple-cache-provider package.

Note: The simple-cache-provider is still an experimental feature, not to be used in a production app.

When initiating createResource, a function is passed which is expected to return a Promise. If the Promise resolves, React carries on and render the results, else, an error is thrown.

The function can then be used in a render function to display the results.

Let’s look at an example of Suspense in action.

We made a custom demo for .
No really. Click here to check it out.

React Suspense Demo

The codebase for the demo can be accessed on GitHub and the live demo can be accessed here.

We’ll be using the create-react-app package to create a new React project, with some modifications. Run the command below in your terminal to generate a React app:

npx create-react-app react-suspense

This creates a folder titled react-suspense which contains the React app. Now, let’s make the aforementioned modifications. To make use of the experimental features such as simple-cache-provider , the React version in the package.json file needs to be bumped up to the alpha version.

Therefore, your package.json file (the dependencies object) should be updated with the code snippet below:

"react": "16.4.0-alpha.0911da3",
"react-dom": "16.4.0-alpha.0911da3",

The alpha version shown above is the version of React we need to carry out our tests. Run the npm install command to update all dependencies.

Let’s also install the simple-cache-provider package with the terminal command below:

npm install simple-cache-provider

With all the dependencies installed, let’s go ahead and write the code that we’ll use to demo Suspense.

The idea here is to get a list of shows from the TV Maze API and then display the results using Suspense.

To begin, we’d need to do some imports in the App.js file. The first will be to import the createResource function in the App.js file. This will be imported from the simple-cache-provider :

import { createResource } from 'simple-cache-provider';

Next, we’ll import a component, not yet created, titled withCache. This is a Higher Order Component (HOC) that helps with Suspense rendering:

import { withCache } from './components/withCache';

Create a folder, name it components and in it create a .withCache.js file and edit with the code below:

import React from 'react';
import { SimpleCache } from 'simple-cache-provider';

export function withCache(Component) {
  return props => (
      {cache => <Component cache={cache} {...props} />}

The withCache component is a Higher Order Component that connects with SimpleCache.Consumer and puts the cache over the wrapped component.

Next, we’ll navigate back to the App.js and create the createResource function to fetch the data:

const sleep = ms => new Promise(r => setTimeout(() => r(), ms));

const readShows = createResource(async function fetchNews() {
  await sleep(3000);
  const res = await fetch(`http://api.tvmaze.com/search/shows?q=suits`);
  return await res.json();

Here’s what the createResource function is doing exactly:

  1. It creates a resource fetcher (createResource()) which is called with a set of parameters, in this case, an async function that fetches the list of shows titled suits, only after ‘waiting’ for the specified duration in the sleep function
  2. It returns the result of the API call

It’s important to note that the sleep function is only being used so as simulate a longer API call for this example.

With the createResource function created, we’ll need to get the results from the async function above and then build the view to display the results. In the App.js file, go ahead and add the code block below:

const Movies = withCache( (props) => {

  return (
      <div className="column is-4">
        <div className="movie">
          <div className="movie__left">
            <img src />
          <div className="movie__right">
            <div className="movie__right__title">Name: </div>
            <div className="movie__right__subtitle">Score: </div>
            <div className="movie__right__subtitle">Status: </div>
            <div className="movie__right__subtitle">Network: </div>
            <a href target="_blank" className="movie__right__subtitle">Link</a>

In the code above, a stateless component is created and wrapped in the withCache Higher Order Component. It returns the necessary HTML to build the view that is needed to display the results from the API.

Also, the Bulma CSS framework is being used to help with styling. That can be added to the project by adding the line of code below to the index.html :

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css">

The next course of action is to actually read the data from the createResource() function and then spit it out into the Movies component.

In the Movie.js component, just before the return function, add the line of code below:

const result = readShows(props.cache);

Here we are using readShows(props.cache) which either resolves the promise value or throws an error. Since readShows is the createResource function, it expects a parameter of cache which is props.cache in this case. The cache is being passed from the withCache HOC as a prop.

The result of the API call is then stored in the result variable. With the API result being fetched, we can now use that to populate the view:

const Movies = withCache( (props) => {

  const result = readShows(props.cache);

  return (
      {result &&
          result.length &&
            result.map(item => (
              <div className="column is-4">
                <div className="movie">
                  <div className="movie__left">
                    <img src={item.show.image.original} />
                  <div className="movie__right">
                    <div className="movie__right__title">{item.show.name}</div>
                    <div className="movie__right__subtitle">Score: {item.show.rating.average}</div>
                    <div className="movie__right__subtitle">Status: {item.show.status}</div>
                    <div className="movie__right__subtitle">Network: {item.show.network ? item.show.network.name : 'N/A'}</div>
                    <a href={item.show.url} target="_blank" className="movie__right__subtitle">Link</a>

Remember we mentioned above, that Suspense helps with async rendering by deferring rendering part of your application tree until some data or resource has been fetched. This is very important as it can be used to display some loading message as a feedback to users who are waiting for data on the screen.

Let’s go ahead and implement this in our app:

const Placeholder = ({ delayMs, fallback, children }) => {
  return (
    <Timeout ms={delayMs}>
      {didExpire => {
        return didExpire ? fallback : children;

The component above accepts the following:

  • ms prop, which indicates the time after which we want to see the fallback content. This is passed to the Placeholder component as delayMS
  • fallback is the loading state that is shown when data is being fetched
  • children which should be a “function as a child” or “render prop” function; this function will be called with one parameter, which indicates if the specified time elapsed

We use the Placeholder component to capture the throw by the fetcher and know the state of the data that’s being loaded.

Pulling all of this together, you can go ahead to edit the App component with the code block below:

export default class App extends React.Component {

  render() {

    return (
        <div className="App">
          <header className="App-header">
            <h1 className="App-title">React Suspense Demo</h1>

          <div className="container">
          <div className="columns is-multiline">
              <Placeholder delayMs={1000} fallback={<div>Loading</div>}>
                <Movies />

As seen above, the Placeholder component is the parent component to the Movies component. The fallback props on the Placeholder component is sent to a nice and simple loading text.

There you have it, you can go ahead to start the app with the npm start command and you should see Suspense in action.


With Suspense, you have the ability to suspend component rendering while async data is being loaded. You can pause any state update until the data is ready, and you can add async loading to any component deep in the tree without plumbing all the props and state through your app and hoisting the logic.

This results in an instantaneous and fluid UI for fast networks and an intentionally designed loading state for slow networks as opposed to a general loading state.

It’s important to note that these APIs are still in experimental mode and not suitable for production. It’s best to always stay in tune with the React team for any API changes and updates to the Suspense feature.

The codebase for the demo above can be accessed on GitHub and the live demo can be accessed here.

You come here a lot! We hope you enjoy the LogRocket blog. Could you fill out a survey about what you want us to write about?

    Which of these topics are you most interested in?
    ReactVueAngularNew frameworks
    Do you spend a lot of time reproducing errors in your apps?
    Which, if any, do you think would help you reproduce errors more effectively?
    A solution to see exactly what a user did to trigger an errorProactive monitoring which automatically surfaces issuesHaving a support team triage issues more efficiently
    Thanks! Interested to hear how LogRocket can improve your bug fixing processes? Leave your email:

    Full visibility into production React apps

    Debugging React applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

    LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

    The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

    Modernize how you debug your React apps — .

    Yomi Eluwande JavaScript Developer. Wannabe Designer and Chief Procrastinator at Selar.co and Worklogs.co

    Leave a Reply