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 tofallback
whenchildren
suspends, and back tochildren
when the data is ready. Iffallback
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
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.
- The
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.
- The
State Management with
useState
- A state variable (
clicked
) is used to determine whether the button has been clicked and subsequently whether theLoadingPage
component should be displayed.
- A state variable (
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.
What are your thoughts on this post?
I’d love to hear from you! Click this link to email me—I reply to every message!
Also use the share button below if you liked this post. It makes me smile, when I see it.