Code Splitting in React with `lazy` and `Suspense`

Published: (January 3, 2026 at 09:41 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Code Splitting in React

In React, code splitting allows us to load parts of our application only when they’re actually needed. Instead of downloading all JavaScript upfront, we can defer loading less‑important or heavy components until the user interacts with the UI. This is especially useful for large applications or components that users may never see.

Why Code Splitting Matters

Benefits

  • Improved performance – Smaller initial JavaScript bundles mean faster page load times, especially on slow networks or low‑end devices.
  • Better user experience – Only essential code is loaded on first render. Additional code is fetched later, exactly when the user needs it.

The Problem: Unnecessary Network Requests

Before using React.lazy and Suspense, the SlowComponent was already loaded in the Network tab, even though:

  • The toggle button was false.
  • The user never opened or saw the component.

This means the browser downloaded code that the user might never use.

Before (without lazy loading)

SlowComponent is loaded immediately on page load:

Browser Network tab showing SlowComponent JavaScript file loaded on initial page load, even though the toggle is false

This is wasted bandwidth and unnecessary work.

The Solution: React.lazy + Suspense

React provides lazy and Suspense to load components only when they’re rendered.

Basic Example

import React, { lazy, Suspense } from 'react';

const DataComponent = lazy(() => import('./DataComponent'));

function MyComponent() {
  return (
    Loading...}>
      
    
  );
}
  • DataComponent is not loaded until it’s actually rendered.
  • A fallback UI is shown while the component is loading.

Practical Example with a Heavy Component

In this example:

  • SlowComponent is heavy and should only load when the user clicks a button.
  • useTransition is used to keep the UI responsive.
import { useState, useTransition, lazy, Suspense } from 'react';

const SlowComponent = lazy(() => import('./SlowComponent'));

const App = () => {
  const [text, setText] = useState('');
  const [items, setItems] = useState([]);
  const [isPending, startTransition] = useTransition();
  const [show, setShow] = useState(false);

  const handleChange = (e) => {
    setText(e.target.value);

    startTransition(() => {
      const newItems = Array.from({ length: 5000 }, (_, index) => (
        
          ![](/vite.svg)
        
      ));
      setItems(newItems);
    });
  };

  return (
    
      
        
      

      
#### Items Below

      {isPending ? (
        'Loading...'
      ) : (
        
          {items}
        
      )}

       setShow(!show)} className="btn">
        Toggle
      

      {show && (
        
          
        
      )}
    
  );
};

export default App;

What Changed in the Network Tab?

After Applying lazy

SlowComponent is not loaded on initial page load:

Browser Network tab showing that SlowComponent JavaScript file is not loaded after page load when lazy loading is applied

Loaded Only on User Action

The component is fetched only when the user clicks the toggle button:

Browser Network tab showing SlowComponent JavaScript file being requested after the user clicks the toggle button

This is exactly what we want.

Key Takeaways

  • Lazy loadingSlowComponent is not downloaded until it’s rendered.
  • Suspense – Handles loading states while the component is fetched.
  • Better performance – No unnecessary JavaScript is loaded upfront.
  • User‑driven loading – Code is fetched only when the user actually needs it.

Optional: Wrapping More with Suspense

If your application contains multiple lazy‑loaded components, you can wrap a larger portion of the component tree with Suspense. In many cases it’s common to wrap the entire return statement so all lazy components share the same loading fallback:


  {/* one or more lazy‑loaded components */}

Conclusion

Before using React.lazy and Suspense, SlowComponent was downloaded even when the toggle was false, meaning users paid the cost for code they might never see.

By using code splitting, we:

  • Reduce the initial bundle size
  • Improve performance
  • Load code only when it’s truly needed

Credits: John Smilga’s course

Back to Blog

Related posts

Read more »