DEV Community

Safal Bhandari
Safal Bhandari

Posted on

Understanding `Suspense` in React and Why It’s Needed for Lazy Loading

When using lazy loading in React with React.lazy(), there’s a period of time when the component is being fetched but not yet available. Without a placeholder, the user would see nothing during that time.

Suspense is React’s built-in solution for handling this gap — it lets you show a fallback UI while the component is loading.


What is Suspense?

Suspense is a React component that wraps around lazily loaded components and displays a fallback (e.g., a loading spinner or message) until they finish loading.

Basic syntax:

<Suspense fallback={<Loading />}>
  <LazyComponent />
</Suspense>
Enter fullscreen mode Exit fullscreen mode

Why is Suspense needed during lazy loading?

  • Without it, React doesn’t know what to render while the component is being downloaded.
  • With it, the user sees a loading state instead of a blank screen.
  • It prevents sudden UI jumps when the component finally appears.

Example Without Suspense

const About = React.lazy(() => import('./About'));

export default function App() {
  return (
    <div>
      <About /> {/* ❌ Will throw an error without Suspense */}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

This will cause an error, because React.lazy requires a Suspense boundary.


Example With Suspense

import React, { Suspense } from 'react';

const About = React.lazy(() => import('./About'));

export default function App() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <About />
      </Suspense>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

How it works:

  1. When <About /> starts loading, React pauses rendering inside Suspense.
  2. The fallback content (e.g., “Loading…”) is shown.
  3. Once <About /> is ready, React replaces the fallback with the actual component.

Suspense with react-router-dom

import React, { Suspense } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

const Home = React.lazy(() => import('./pages/Home'));
const About = React.lazy(() => import('./pages/About'));

export default function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading page...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </Router>
  );
}
Enter fullscreen mode Exit fullscreen mode

Here, the fallback UI is shown whenever a route’s component is still being fetched.


Best Practices

  • Keep fallback UIs lightweight (spinner, skeleton loader, short text).
  • Use nested Suspense boundaries for different sections (so not everything waits if only part of the page is loading).
  • Avoid keeping users waiting too long — break up huge chunks of code into smaller lazy-loaded pieces.

Key takeaway:
Suspense is the safety net for lazy loading. Without it, React can’t render anything until the lazy-loaded component is ready, leading to errors or blank screens. With it, users see a smooth loading state while your app fetches components on demand.


Top comments (0)