React Suspense Explained — Manage Loading States Declaratively
In this tutorial, you will learn about React Suspense Explained. We cover key concepts, practical examples, and best practices to help you master this topic.
React Suspense lets components wait for something before rendering, showing a fallback like a spinner while asynchronous dependencies like data or code are loading.
What You'll Learn
- What Suspense is and how it works
- How to use Suspense for Code Splitting with React.lazy
- How to nest Suspense boundaries
- How to handle errors with Suspense
- How data fetching with Suspense works
Why It Matters
Suspense shifts loading state management from the component level to the framework level. Instead of if (loading) return <Spinner /> in every component, Suspense handles it declaratively.
Real-World Use
Durga Antivirus Pro uses Suspense boundaries for each dashboard section. While the ThreatGraph data loads, a skeleton placeholder shows. When analytics data loads, a chart placeholder appears. Each section loads independently.
flowchart LR
A[Suspense Boundary] --> B[Fallback UI]
A --> C[Child Component]
C --> D{Data Ready?}
D -->|No| B
D -->|Yes| E[Render Content]
style A fill:#3b82f6,color:#fff
Suspense with React.lazy
Lazy load components with Suspense:
import { Suspense, lazy } from "react";
import { Routes, Route } from "react-router-dom";
const Dashboard = lazy(() => import("./pages/Dashboard"));
const Settings = lazy(() => import("./pages/Settings"));
const Reports = lazy(() => import("./pages/Reports"));
function LoadingFallback() {
return (
<div className="skeleton" style={{ padding: 20 }}>
<div style={{ height: 24, background: "#e5e7eb", borderRadius: 4, marginBottom: 16 }} />
<div style={{ height: 200, background: "#e5e7eb", borderRadius: 8 }} />
</div>
);
}
function App() {
return (
<Suspense fallback={<LoadingFallback />}>
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
<Route path="/reports" element={<Reports />} />
</Routes>
</Suspense>
);
}
Expected output: While each page component loads, a skeleton placeholder shows. Once loaded, the component renders. Navigating to another page shows the fallback again briefly.
Each route's component is code-split. Suspense shows the fallback during the brief loading period, providing visual feedback instead of a blank screen.
Common Mistakes
- Not wrapping lazy components in Suspense
- Using one Suspense boundary for the entire app
- Placing Suspense inside the component that suspends
- Forgetting that Suspense requires a concurrent-compatible data library
- Not handling errors with error boundaries alongside Suspense
Practice Questions
- What does Suspense render while loading?
- How do you lazy load a component?
- Can you nest Suspense boundaries?
- How do you handle errors in Suspense?
- What data fetching libraries support Suspense?
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro