REACT Suspense

Suspense helps manage loading states for components that rely on asynchronous operations, such as fetching data or dynamically loading components (code splitting).

How does Suspense work?

React Suspense works by wrapping a component that has asynchronous behavior, and while that component is waiting to load, React will “suspend” rendering and show a fallback UI until the operation is complete.

1. Basic Example of Suspense

Here’s a basic example of how Suspense can be used with a lazy-loaded component.

Step 1: Import React and Suspense

import React, { Suspense, lazy } from "react";

Try It Now

Step 2: Use React.lazy for Lazy Loading

React provides the React.lazy() function to dynamically import a component when it’s needed.

const LazyComponent = lazy(() => import("./LazyComponent"));

Try It Now

Step 3: Wrap with Suspense

Now, wrap the lazy-loaded component inside a <Suspense> component and provide a fallback UI (such as a loading spinner) until the component finishes loading.

const App = () => {
  return (
    <div>
      <h1>React Suspense Example</h1>
      <Suspense fallback={<div>Loading...</div>}>
        <LazyComponent />
      </Suspense>
    </div>
  );
};

export default App;

Try It Now

  • LazyComponent will be loaded only when needed.
  • If it takes time to load, Suspense will display the “Loading…” message until the component is ready.

 

2. Suspense with Data Fetching (React 18+)

In React 18 and beyond, Suspense can also be used with data fetching in conjunction with React’s new concurrent rendering. Suspense helps in delaying rendering until data is ready, providing a smoother user experience.

Using Suspense with Data Fetching

React doesn’t have built-in support for data fetching out of the box with Suspense, but you can integrate it with libraries like Relay or React Query.

Step 1: Create a “Suspense-Friendly” Fetcher

You need to create a function that “throws” a promise when data is not yet available. This is how Suspense knows to suspend rendering.

// Simulated fetch function for data
const fetchData = () => {
  let data = null;
  const promise = new Promise((resolve) => {
    setTimeout(() => {
      data = { message: "Data fetched successfully!" };
      resolve(data);
    }, 2000); // Simulating a delay of 2 seconds
  });

  // Throw the promise while it's loading
  if (!data) {
    throw promise;
  }

  return data;
};

Try It Now

Step 2: Create the Component Using Suspense

Now, use the fetcher inside a component.

const DataComponent = () => {
  const data = fetchData(); // Data fetching simulated
  return <h1>{data.message}</h1>;
};

const App = () => {
  return (
    <div>
      <h1>Data Fetching with Suspense</h1>
      <Suspense fallback={<div>Loading data...</div>}>
        <DataComponent />
      </Suspense>
    </div>
  );
};

export default App;

Try It Now

In this example:

  • fetchData simulates a delayed fetch and throws a promise.
  • Suspense will wait for the data to be fetched, and while waiting, it will show the fallback UI (e.g., “Loading data…”).

3. Suspense with Multiple Components

You can wrap multiple components with a single <Suspense> component to handle the loading state for all of them.

const Component1 = lazy(() => import("./Component1"));
const Component2 = lazy(() => import("./Component2"));

const App = () => {
  return (
    <div>
      <h1>Suspense with Multiple Components</h1>
      <Suspense fallback={<div>Loading components...</div>}>
        <Component1 />
        <Component2 />
      </Suspense>
    </div>
  );
};

Try It Now

React will handle the loading for all components wrapped within the <Suspense> component.

4. Suspense in Concurrent Mode (React 18)

React 18 introduces Concurrent Mode, which works alongside Suspense to make rendering more efficient and seamless. With Concurrent Mode, Suspense can give React more control over when and how to update the UI, improving performance in large applications.

How Concurrent Mode Changes Suspense:

  • Suspense enables interruptible rendering: React can pause rendering, load the data, and continue where it left off without blocking the UI.
  • The fallback UI can be shown as React is fetching or processing data, allowing the UI to remain responsive.

5. Performance Optimization with Suspense

Suspense improves performance by allowing code splitting and lazy loading of components, which results in smaller initial JavaScript bundles. Only the necessary components and data are loaded when needed.

Best Practices:

  1. Lazy Load Routes: Load different pages or parts of the app on demand, rather than loading everything at once.
  2. Defer Non-Essential Data: Only load data when it’s required to render a component, and display a loading state in the meantime.
  3. Use Suspense for Libraries: Use Suspense to lazily load heavy libraries or third-party components.