- Animation
- Bootstrap
- Button
- Components
- Conditional rendering
- Context API
- Debounce
- Error boundary
- Events
- Form
- Fragment
- Hooks
- Inline styling
- Key
- Lazy loading
- Lifecycle methods
- Portal
- Prop types
- Props
- Redux library
- Ref
- Router
- State
- State management
- Strict mode
- Suspense
- useCallback Hook
- useEffect hook
- useMemo hook
- useReducer hook
- useRef hook
- Virtual DOM
REACT
React Suspense: Syntax, Usage, and Examples
React Suspense
is a powerful feature for handling asynchronous rendering in React applications. It lets you “pause” rendering while data or components are loading, and display a fallback UI instead—like a loading spinner or message.
How to Use Suspense in React
To use Suspense React
components, wrap the part of your UI that might need to wait for something (like a lazy-loaded component) inside a <Suspense>
boundary. You must also provide a fallback
prop, which is rendered while the content is still loading.
Basic Syntax
import React, { Suspense, lazy } from 'react';
const LazyComponent = lazy(() => import('./MyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
In this example, React will load MyComponent
asynchronously. While it’s loading, the UI shows “Loading…”. Once the component is ready, it renders in place.
Suspense
: The boundary that waitsfallback
: The UI shown while loadinglazy()
: A function that enables dynamic importing of components
When to Use Suspense in React
The React suspense
feature is useful anytime your UI depends on something asynchronous. While it originally supported only code-splitting, recent improvements extend its utility to data fetching, especially when combined with libraries like React Query.
Lazy-Loading Components
Suspense is ideal for deferring component loading until it’s needed. This improves initial load time and performance.
const Chart = lazy(() => import('./Chart'));
<Suspense fallback={<div>Loading chart...</div>}>
<Chart />
</Suspense>
This is especially helpful in dashboards, analytics tools, or any app with heavy visual components.
Data Fetching with React Query Suspense
When using React Query, you can enable suspense mode so your data-fetching logic integrates directly with Suspense.
const queryClient = new QueryClient({
defaultOptions: {
queries: {
suspense: true,
},
},
});
Then in your component:
const { data } = useQuery(['user', userId], fetchUser);
<Suspense fallback={<p>Loading user...</p>}>
<UserProfile user={data} />
</Suspense>
This allows you to avoid managing loading states manually. Instead, you delegate that to react query suspense
, which works seamlessly with Suspense boundaries.
Coordinating Multiple Async Operations
If you have multiple components each fetching different data, wrapping them in a shared Suspense boundary lets you coordinate them cleanly.
<Suspense fallback={<div>Loading all widgets...</div>}>
<WidgetA />
<WidgetB />
<WidgetC />
</Suspense>
This avoids each widget needing its own spinner and simplifies the visual feedback for users.
Examples of Suspense in React
Let’s look at a few hands-on cases where Suspense improves your codebase’s clarity and performance.
Example 1: Basic Lazy Component
import React, { Suspense, lazy } from 'react';
const Profile = lazy(() => import('./Profile'));
function Dashboard() {
return (
<Suspense fallback={<div>Loading profile...</div>}>
<Profile />
</Suspense>
);
}
This defers the loading of the Profile component, improving the performance of the initial render.
Example 2: Nested Suspense
You can nest multiple Suspense boundaries to control loading feedback at a granular level.
<Suspense fallback={<div>Loading page...</div>}>
<Header />
<Suspense fallback={<div>Loading content...</div>}>
<MainContent />
</Suspense>
</Suspense>
This setup allows the header to show immediately while the main content loads separately, offering a smoother experience.
Example 3: react suspense example with Data Fetching
Here's how to combine Suspense with React Query in a more realistic scenario.
import { useQuery } from '@tanstack/react-query';
function UserProfile() {
const { data } = useQuery(['user'], fetchUserData);
return <div>Hello, {data.name}</div>;
}
function App() {
return (
<Suspense fallback={<div>Loading user data...</div>}>
<UserProfile />
</Suspense>
);
}
This example highlights a clean data-fetching flow using suspense React
integration with query hooks.
Learn More About Suspense in React
Concurrent Features and Future Potential
React Suspense plays a central role in React’s long-term vision of concurrent rendering. It works best with React 18’s concurrent features like startTransition
, automatic batching, and the use
hook.
For example:
import { startTransition } from 'react';
startTransition(() => {
setSearchQuery(newQuery);
});
In the future, you'll be able to combine Suspense with streaming server-rendered content, allowing portions of a page to load progressively without blocking the entire UI.
Error Boundaries with Suspense
Suspense only handles “waiting.” For error handling, you still need error boundaries.
<ErrorBoundary fallback={<div>Something went wrong.</div>}>
<Suspense fallback={<div>Loading...</div>}>
<Profile />
</Suspense>
</ErrorBoundary>
This ensures your app doesn’t crash if the component fails to load or fetch data.
Handling Fallback Content Gracefully
Instead of using plain <div>Loading...</div>
, you can use richer fallback components to create better user experiences.
<Suspense fallback={<SkeletonCard />}>
<UserCard />
</Suspense>
You can even animate transitions between fallback and real content, creating smooth fade-ins or skeleton loading states.
Suspense with useTransition and useDeferredValue
React 18 adds hooks like useTransition
and useDeferredValue
that help you better coordinate UI updates with Suspense.
const [isPending, startTransition] = useTransition();
startTransition(() => {
setValue(newValue);
});
Combined with Suspense, this lets you prioritize quick interactions (like button clicks) and delay expensive renders (like charts).
Server Components and Suspense
React Server Components rely heavily on Suspense. They allow you to render parts of your application on the server and progressively stream them to the client.
<Suspense fallback={<div>Loading server component...</div>}>
<ServerRenderedComponent />
</Suspense>
You’ll see more of this in frameworks like Next.js 13+ with app directory structure.
react suspense example in Next.js
If you're using Next.js, you can wrap server components or dynamic imports in Suspense just like in regular React:
import dynamic from 'next/dynamic';
import { Suspense } from 'react';
const DynamicChart = dynamic(() => import('../components/Chart'), {
suspense: true,
});
export default function Dashboard() {
return (
<Suspense fallback={<div>Loading chart...</div>}>
<DynamicChart />
</Suspense>
);
}
This is a great react suspense example
that aligns with best practices in full-stack React apps.
React Suspense helps you write smoother, cleaner, and faster apps without wrestling with dozens of loading states. By treating loading like a first-class UI concept, it clears the path for better user experiences and more maintainable code. As support grows in tools like React Query and Next.js, Suspense is quickly becoming a must-have in every React developer’s toolkit.
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.