Suspense and Lazy Loading

Back

Loading concept...

Concurrent React: Suspense and Lazy Loading 🚀

The Restaurant Analogy 🍽️

Imagine you’re at a busy restaurant. When you order food, you don’t have to wait at the kitchen door. Instead, you sit at your table, maybe sip some water, and the waiter brings your food when it’s ready.

React Suspense works exactly like this restaurant!

  • Your app is the restaurant
  • Components are the dishes you order
  • Suspense is the waiter who handles the waiting
  • Fallbacks are the bread basket while you wait

1. Suspense Fundamentals

What is Suspense?

Suspense is React’s way of saying: “Hey, some stuff isn’t ready yet. Let me show something else while we wait!”

Think of it like a magic placeholder. When your app needs to load something (like data or a component), Suspense shows a temporary thing until the real thing arrives.

Simple Example

import { Suspense } from 'react';

function App() {
  return (
    <Suspense fallback={<p>Loading...</p>}>
      <SlowComponent />
    </Suspense>
  );
}

What happens here?

  1. React tries to show SlowComponent
  2. If it’s not ready, React shows “Loading…”
  3. When ready, the real component appears!

2. Suspense Boundaries

What is a Suspense Boundary?

A boundary is like a fence around your garden. Everything inside the fence follows the same rules.

A Suspense boundary catches any “loading” state from components inside it.

graph TD A["App"] --> B["Suspense Boundary"] B --> C["Loading Component A"] B --> D["Loading Component B"] B --> E["Loading Component C"] style B fill:#f9f,stroke:#333,stroke-width:2px

Why Use Boundaries?

Without boundaries, your whole app might show a spinner. With boundaries, only the loading part shows a spinner.

Multiple Boundaries Example

function App() {
  return (
    <div>
      <Header /> {/* Shows immediately */}

      <Suspense fallback={<p>Loading posts...</p>}>
        <Posts /> {/* Has its own loading */}
      </Suspense>

      <Suspense fallback={<p>Loading comments...</p>}>
        <Comments /> {/* Separate loading */}
      </Suspense>
    </div>
  );
}

Result: Header shows instantly. Posts and Comments load separately!


3. Suspense Fallbacks

What is a Fallback?

A fallback is what your users see while waiting. It’s like the coming soon sign at a movie theater.

Good Fallback Examples

// Simple text
<Suspense fallback={<p>Loading...</p>}>

// Spinner component
<Suspense fallback={<Spinner />}>

// Skeleton screen (looks like content)
<Suspense fallback={<ContentSkeleton />}>

The Best Fallbacks

Skeleton screens are the best! They show the shape of content before it loads.

function PostSkeleton() {
  return (
    <div className="skeleton">
      <div className="skeleton-title" />
      <div className="skeleton-text" />
      <div className="skeleton-text" />
    </div>
  );
}

// Usage
<Suspense fallback={<PostSkeleton />}>
  <Post />
</Suspense>

4. The use Hook

What is use?

The use hook is brand new in React 19. It lets you read promises and context directly inside components.

Think of it as a magic reader that:

  • Waits for promises automatically
  • Works with Suspense out of the box
  • Makes async code look like normal code

Example with use

import { use, Suspense } from 'react';

function Posts({ postsPromise }) {
  // use() waits for the promise!
  const posts = use(postsPromise);

  return (
    <ul>
      {posts.map(post => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

function App() {
  const postsPromise = fetchPosts();

  return (
    <Suspense fallback={<p>Loading...</p>}>
      <Posts postsPromise={postsPromise} />
    </Suspense>
  );
}

Key Rules for use

  1. âś… Can be called inside if statements
  2. âś… Can be called inside loops
  3. ❌ Cannot be called outside components
  4. ⚠️ Only works with Suspense

5. React.lazy

What is React.lazy?

React.lazy is like ordering a pizza delivery. You don’t go to the pizza shop yourself. Instead, you call them and they bring it to you when it’s ready.

With React.lazy, components load only when needed.

Basic Example

import { lazy, Suspense } from 'react';

// This doesn't load immediately!
const HeavyChart = lazy(() =>
  import('./HeavyChart')
);

function Dashboard() {
  return (
    <Suspense fallback={<p>Loading chart...</p>}>
      <HeavyChart />
    </Suspense>
  );
}

Why Use React.lazy?

  • 📦 Smaller initial download - Users download less at start
  • ⚡ Faster loading - App appears quicker
  • đź’ľ Saves bandwidth - Only load what’s needed

6. Dynamic Imports

What are Dynamic Imports?

Normal imports load everything at once:

// Loads immediately when app starts
import HeavyLibrary from 'heavy-library';

Dynamic imports load on demand:

// Loads only when this code runs
const HeavyLibrary = await import('heavy-library');

The Magic of import()

import() returns a promise. It’s like saying “go fetch this, and tell me when it’s here.”

async function loadEditor() {
  // Only loads when function is called
  const module = await import('./RichTextEditor');
  return module.default;
}

Common Pattern

const LazyComponent = lazy(() => import('./MyComponent'));

This combines:

  1. import() - Dynamic loading
  2. lazy() - React integration
  3. Suspense - Loading state handling

7. Code Splitting Basics

What is Code Splitting?

Imagine a huge book. Instead of carrying the whole book everywhere, you only bring the chapter you’re reading.

Code splitting breaks your app into smaller pieces (called chunks).

graph TD A["Your Big App"] --> B["Main Bundle"] A --> C["Admin Bundle"] A --> D["Chart Bundle"] A --> E["Editor Bundle"] style A fill:#ffcc00,stroke:#333

Before Code Splitting

📦 bundle.js (2.5 MB) - Everything in one file
   ├── React
   ├── Your components
   ├── Chart library
   ├── Editor library
   └── Admin pages

After Code Splitting

📦 main.js (200 KB) - Only essentials
📦 charts.js (500 KB) - Loads when needed
📦 editor.js (800 KB) - Loads when needed
📦 admin.js (300 KB) - Loads when needed

How to Split Code

// Create separate chunks automatically
const Charts = lazy(() => import('./Charts'));
const Editor = lazy(() => import('./Editor'));
const Admin = lazy(() => import('./Admin'));

Each import() creates a new chunk (separate file).


8. Route-Based Splitting

The Best Place to Split

Routes are perfect for code splitting! Why?

  • Users only visit one page at a time
  • Pages are often independent
  • Natural loading points (page navigation)

Example with React Router

import { lazy, Suspense } from 'react';
import {
  BrowserRouter,
  Routes,
  Route
} from 'react-router-dom';

// Lazy load each page
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
const Dashboard = lazy(() =>
  import('./pages/Dashboard')
);

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<PageLoader />}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/dashboard" element={<Dashboard />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

The Result

graph TD A["User visits /"] --> B["Loads Home chunk only"] A --> |Later clicks About| C["Loads About chunk"] A --> |Later clicks Dashboard| D["Loads Dashboard chunk"] style B fill:#90EE90 style C fill:#ADD8E6 style D fill:#FFB6C1

Quick Summary 🎯

Concept What It Does Like…
Suspense Handles loading states A waiter at restaurant
Boundaries Isolate loading areas Fences around gardens
Fallbacks Shows while loading “Coming soon” sign
use hook Reads promises easily Magic promise reader
React.lazy Loads components later Pizza delivery
Dynamic import Loads code on demand Ordering when hungry
Code splitting Breaks app into chunks Book chapters
Route splitting Splits by pages One chapter per trip

Your React App is Now Faster! 🚀

You learned how to:

  1. âś… Wrap slow stuff in Suspense
  2. âś… Create smart boundaries
  3. âś… Show helpful fallbacks
  4. âś… Use the new use hook
  5. âś… Lazy load with React.lazy
  6. âś… Split code into chunks
  7. âś… Optimize routes

Remember the restaurant: Good service means customers don’t stare at the kitchen. Good React apps show something useful while loading!

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.