Understanding Suspense

React Suspense comes handy when you want to show an indication to user that something is loading in your app. Loader is the simplest example for a Suspense component. Let’s deep dive into the details of Suspense.

What is Suspense?

<Suspense> lets you display a fallback until its children have finished loading.
— React Docs

Syntax:

<Suspense fallback={<Loading />}>
  <SomeComponent />
</Suspense>

Props

  • children: The actual UI component you need to render. If children suspends while rendering, the Suspense boundary will switch to rendering fallback.

  • fallback: An alternate UI to render in place of the actual UI if it has not finished loading. Any valid React node is accepted here, but a lightweight loader like loading spinner or skeleton is recommended. Suspense will automatically switch to fallback when children suspends, and back to children when the data is ready. If fallback suspends while rendering, it will activate the closest parent Suspense boundary.

Usage

  • Displaying a fallback while content is loading.
  • Revealing content together at once.
  • Revealing nested content as it loads.
  • Showing stale content while fresh content is loading.
  • Preventing already revealed content from hiding.
  • Indicating that a Transition is happening.
  • Resetting Suspense boundaries on navigation.
  • Providing a fallback for server errors and client-only content.

Example:

To better understand this concept, let’s dive into an example where we use a fallback component during content loading, combined with lazy loading.

In the example below, the LoadingPage component is lazily loaded, and a fallback component (Loading) is provided via the fallback prop of the Suspense component. The Suspense component ensures that while LoadingPage is being loaded, the Loading component is displayed as a placeholder.

import { Suspense, lazy, useState } from "react"; 
import Loading from "./Loading"; 

// Dynamically import the `LoadingPage` component. This delays the loading of this component until it's needed.
const LoadingPage = lazy(() => import("./LoadingPage")); 

export default function HomePage() { 
  const [clicked, setClicked] = useState(false); 

  function btnClickHandler() { 
    setClicked(!clicked); 
  }

  // Use React's Suspense to handle lazy loading. While `LoadingPage` is being loaded, show the `Loading` component.
  return (
    <>
      <h2>Home page</h2> 
      <button onClick={btnClickHandler}>Click here</button> 

      {clicked && ( 
        <Suspense fallback={<Loading />}> 
          <LoadingPage /> 
        </Suspense>
      )}
    </>
  );
}

The fallback component, Loading, is defined separately:

export default function Loading() {
    return <p><i>Loading...</i></p>;
}

How It Works

  1. Lazy Loading with lazy()

    • The LoadingPage component is not loaded initially but only when it is needed (after the button is clicked).
    • This improves the initial load time of the application by splitting code into smaller bundles.
  2. Suspense as a Wrapper

    • The Suspense component acts as a boundary that waits for the lazily loaded component (LoadingPage) to finish loading.
    • During this time, the fallback component (Loading) is displayed, providing feedback to the user.
  3. State Management with useState

    • A state variable (clicked) is used to determine whether the button has been clicked and subsequently whether the LoadingPage component should be displayed.
  4. Fallback Component (Loading)

    • This component provides a visual indicator (in this case, a “Loading…” message) to keep users engaged while the actual component is being fetched.

Summary

By combining Suspense and lazy, we can dynamically load components in React, improving performance and optimizing user experience. The fallback mechanism provided by Suspense ensures that users are never left staring at a blank screen during load times.

This approach is especially useful for large applications where certain parts of the app (like modal dialogs, routes, or additional pages) don’t need to be loaded immediately.

Example repository

Check out the full working examples in the GitHub Repository.

References

Suspense, React Lazy

Read More