What are React.lazy and Suspense?
Learn how React.lazy and Suspense enable code-splitting and lazy loading to shrink your bundle, speed up first load, with examples and interview questions.
Expected Interview Answer
React.lazy lets you load a component's code on demand as a separate bundle instead of upfront, and Suspense shows a fallback UI (like a spinner) while that lazily-loaded component is still being fetched.
React.lazy takes a function that calls a dynamic import() and returns a component that only downloads when it is first rendered — this is code-splitting. Because the code arrives asynchronously, the lazy component must be wrapped in a Suspense boundary whose fallback prop renders while the chunk loads. Together they shrink the initial JavaScript bundle, speeding up first load, and defer non-critical code until it is actually needed.
- Smaller initial bundle and faster first paint
- Loads code only when a component is actually rendered
- Declarative loading UI via Suspense fallback
- Route-level and component-level code splitting
- Better Core Web Vitals on mobile
- Cleaner than manual dynamic-import wiring
AI Mentor Explanation
React.lazy is like keeping your death-overs specialist in the pavilion until the 40th over instead of tiring him out early. Suspense is the twelfth man who fields as a stand-in while the specialist pads up. The bowler's code is only fetched when the situation actually needs him, and the crowd sees a fallback fielder in the meantime rather than an empty spot on the ground.
Step-by-Step Explanation
Step 1
Convert to a dynamic import
Wrap the component import in React.lazy(() => import('./HeavyComponent')).
Step 2
Wrap in Suspense
Place the lazy component inside a <Suspense fallback={...}> boundary.
Step 3
Provide a fallback
Give the fallback prop a spinner or skeleton to show while the chunk loads.
Step 4
Split at the right level
Apply it per route or to large, rarely-used widgets to maximise bundle savings.
Step 5
Handle load failures
Wrap the boundary in an Error Boundary so a failed chunk fetch shows a graceful error, not a blank screen.
What Interviewer Expects
- Knows React.lazy enables code-splitting via dynamic import
- Understands Suspense provides the loading fallback
- Can explain why lazy components must be wrapped in Suspense
- Mentions route-level splitting as a common use
- Knows to pair with an Error Boundary for load failures
Common Mistakes
- Using React.lazy without wrapping it in Suspense
- Trying to lazy-load a named export without adapting the import
- Overusing it on tiny components where splitting adds overhead
- Forgetting an Error Boundary so failed fetches crash the UI
- Expecting lazy to work for non-default exports directly
Best Answer (HR Friendly)
“React.lazy lets an app download a piece of its code only when it is actually needed instead of all at once, which makes the first load faster. Suspense shows a temporary loading message, like a spinner, while that piece is being fetched.”
Code Example
import { lazy, Suspense } from 'react'
const Dashboard = lazy(() => import('./Dashboard'))
export default function App() {
return (
<Suspense fallback={<p>Loading dashboard...</p>}>
<Dashboard />
</Suspense>
)
}Follow-up Questions
- Why must a lazy component be wrapped in Suspense?
- How do you lazy-load a component that uses a named export?
- How does React.lazy relate to code-splitting and dynamic import?
- What happens if the chunk fails to download?
- How do you combine Suspense with an Error Boundary?
MCQ Practice
1. What must you pass to React.lazy?
React.lazy takes a function that calls import(), which returns a promise resolving to a module with a default export.
2. Why does a lazy component need Suspense?
Because the code loads asynchronously, Suspense renders the fallback UI until the chunk has arrived.
3. What is the main performance benefit of React.lazy?
It splits code into chunks loaded on demand, reducing the JavaScript needed for the first paint.
Flash Cards
What does React.lazy do? — Loads a component's code on demand via dynamic import() instead of in the initial bundle.
What does Suspense provide? — A fallback UI (e.g. a spinner) shown while a lazy component's code is loading.
Can lazy be used without Suspense? — No — a lazy component must be rendered inside a Suspense boundary.
How do you handle a failed chunk load? — Wrap the Suspense boundary in an Error Boundary to show a graceful error.