How Suspense works?

React Suspense uses exception control flow. It is related to JavaScript Promise. Regardless, whether if you are using traditional new Promise() or async/await syntax, a JavaScript Promise always has 3 states.

  • pending
  • resolve
  • rejected

If code is throwing exception (while loading data or if rejected), react suspense shows fallback UI. If resolved successfully, it will show the child component.

Working example of React Suspense

Example: To demonsrtate using <Suspense /> component to manage our loading state.

Node
//App.tsx

import { Suspense } from "react";
import "./App.css";
import AsyncComponent from "./async-comp";

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <AsyncComponent />
    </Suspense>
  );
}

export default App;


Node
//async-comp.tsx

import fetchData from "./api/fetch-data";

const promise = fetchData<{ title: string }[]>(
  "https://jsonplaceholder.typicode.com/todos"
);

export default function AsyncComponent() {
  const data = promise.read();

  return (
    <ul>
      {data.map((item, index) => (
        <li key={index}>{item.title}</li>
      ))}
    </ul>
  );
}


Node
//fetch-data.ts

export default function fetchData<T>(url: string) {
  const promise: Promise<T> = fetch(url)
    .then((res) => res.json())
    .then((data) => data);

  return wrapPromise(promise);
}


function wrapPromise<T>(promise: Promise<T>) {
  let status = "pending";
  let response: T;

  const suspender = promise.then(
    (res) => {
      status = "success";
      response = res;
    },
    (err) => {
      status = "error";
      response = err;
    }
  );

  const read = () => {
    switch (status) {
      case "pending":
        throw suspender;
      case "error":
        throw response;
      default:
        return response;
    }
  };

  return { read };
}

In fetchData function, we are creating a promise and chaining it with .then() to parse JSON. Then passing the promise to wrapPromise which initialises status.

Output

Fallback Loading UI using suspense

Using Suspense gives some major improvements compared to previous approaches.

  1. Data fetching starts as soon as possible and rendering of components starts immediately.
  2. We do not have to manage loading state, react does that for us.
  3. Child components do not need to wait for their parent component’s data to finish fetching before they can fetch their data.

How does Suspense help in Handling Asynchronous Operations in React ?

Suspense, first introduced in React 16, is a feature that aims to enhance the user experience by managing asynchronous operations. It simply lets you render a fallback UI decoratively while the child component is waiting for any asynchronous task to be completed.

Table of Content

  • What is React Suspense?
  • Project Initialisation
  • Traditional Data Fetching Techniques
  • How Suspense works?
  • Use cases of React Suspense
  • Suspense with Server Components in Next.js
  • Conclusion

Prerequisites:

Similar Reads

What is React Suspense?

Suspense allows developers to display a temporary fallback UI when the component is doing the asynchronous operation. When the operation is completed, the actual UI is rendered. Suspense can be used when a child component is lazily loaded or fetching data....

Project Initialisation

Initialise a react project. In this example project, we will use TypeScript, but if you are not comfortable with it, use JavaScript....

Traditional Data Fetching Techniques

Fetch on Render:...

How Suspense works?

React Suspense uses exception control flow. It is related to JavaScript Promise. Regardless, whether if you are using traditional new Promise() or async/await syntax, a JavaScript Promise always has 3 states....

Use cases of React Suspense

1. Revealing nested components while data is loading...

Suspense with Server Components in Next.js

In next.js, we can create a special file called loading.js (or .jsx) for specific route or in root level that automatically wraps page.jsx and other nested routes. We can have small components like spinner, skeleton that are pre-rendered and can be instantly shown while page is loading data. We can define define laoding.jsx in for every route. We can even change the behaviour by defining our own suspense....

Conclusion

In this article, we have explored React Suspense, its benefits, functionality, and practical application through a hands-on React project demonstration. We have covered how Suspense redefines data fetching patterns, addresses loading state challenges, how Suspense works under the hood, and how to use it with React meta-frameworks like Next.js. By mastering Suspense, we have elevated our React development skills and streamlined our application’s performance....