REACT

React Lazy Loading: Syntax, Usage, and Examples

React lazy loading is a technique that delays loading certain components until they are needed, improving performance by reducing the initial bundle size. Instead of loading everything at once, lazy loading ensures that only the required code is fetched when necessary.

How to Use React Lazy Loading

React provides built-in support for lazy loading through React.lazy() and Suspense. To enable lazy loading, import components dynamically and wrap them inside a Suspense boundary.

Basic Syntax

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

const LazyComponent = lazy(() => import("./LazyComponent"));

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

export default App;
  • lazy(() => import("./LazyComponent")) dynamically imports the component when needed.
  • Suspense displays a fallback (like a loading message) until the component is ready.

When to Use React Lazy Loading

Large Components That Are Not Always Needed

If a component is only required for specific user interactions, such as a modal, it can be lazy-loaded instead of being part of the initial bundle.

Multi-Page Applications with Code Splitting

Lazy loading is helpful for React applications with multiple pages where users may not visit every route. By implementing lazy loading in React, you can reduce the amount of JavaScript loaded upfront.

Third-Party Libraries and Heavy Components

Libraries like charts, maps, or rich text editors often include large dependencies. Lazy loading ensures these dependencies are only fetched when necessary.

Examples of React Lazy Loading

Lazy Loading Multiple Components

You can apply lazy loading to multiple components within a routing setup using React Router.

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

const Home = lazy(() => import("./Home"));
const About = lazy(() => import("./About"));

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </Router>
  );
}

export default App;

Now, React only loads the required component when the user navigates to that route.

Lazy Loading with Dynamic Imports

You can lazy load components dynamically based on user actions.

import React, { Suspense, lazy, useState } from "react";

const Chart = lazy(() => import("./Chart"));

function Dashboard() {
  const [showChart, setShowChart] = useState(false);

  return (
    <div>
      <button onClick={() => setShowChart(true)}>Show Chart</button>
      <Suspense fallback={<div>Loading Chart...</div>}>
        {showChart && <Chart />}
      </Suspense>
    </div>
  );
}

export default Dashboard;

The Chart component is loaded only when the user clicks the button.

Lazy Loading React Components with a Custom Fallback

Instead of using simple text as a fallback, you can display a spinner or animation while the component loads.

import React, { Suspense, lazy } from "react";
import Loader from "./Loader";

const Dashboard = lazy(() => import("./Dashboard"));

function App() {
  return (
    <Suspense fallback={<Loader />}>
      <Dashboard />
    </Suspense>
  );
}

export default App;

This approach improves user experience by providing visual feedback while loading.

Learn More About React Lazy Loading

Handling Errors in Lazy Loaded Components

If an error occurs while loading a component, you can catch it using React.ErrorBoundary.

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

const Profile = lazy(() => import("./Profile"));

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  render() {
    if (this.state.hasError) {
      return <h2>Something went wrong.</h2>;
    }
    return this.props.children;
  }
}

function App() {
  return (
    <ErrorBoundary>
      <Suspense fallback={<div>Loading...</div>}>
        <Profile />
      </Suspense>
    </ErrorBoundary>
  );
}

export default App;

This ensures that if a lazy-loaded component fails, a user-friendly error message appears instead of breaking the entire application.

Preloading Lazy Loaded Components

Sometimes, you may want to preload a component before the user interacts with it. You can achieve this using import() before rendering.

const preloadedComponent = import("./HeavyComponent");

function preloadComponent() {
  preloadedComponent.then(module => {
    console.log("Component preloaded", module);
  });
}

You can trigger preloadComponent() based on user actions or conditions to improve perceived performance.

Lazy Loading Images

Lazy loading in React is not limited to components. You can also defer image loading using the loading="lazy" attribute in <img> elements.

<img src="large-image.jpg" alt="Lazy loaded" loading="lazy" />

This prevents large images from loading until they enter the viewport, improving page speed.

Lazy Loading with Intersection Observer

For components that should load when they become visible, you can combine lazy loading with IntersectionObserver.

import React, { useState, useEffect, Suspense, lazy } from "react";

const LazyComponent = lazy(() => import("./LazyComponent"));

function LazyWrapper() {
  const [isVisible, setIsVisible] = useState(false);
  const ref = React.useRef();

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        setIsVisible(true);
        observer.disconnect();
      }
    });
    if (ref.current) {
      observer.observe(ref.current);
    }
    return () => observer.disconnect();
  }, []);

  return (
    <div ref={ref} style={{ minHeight: "200px" }}>
      {isVisible ? (
        <Suspense fallback={<div>Loading component...</div>}>
          <LazyComponent />
        </Suspense>
      ) : (
        <p>Scroll down to load the component</p>
      )}
    </div>
  );
}

export default LazyWrapper;

This approach loads components only when they enter the viewport, making it useful for optimizing long pages.

Combining Lazy Loading with Code Splitting

React’s React.lazy() is useful for splitting large JavaScript bundles into smaller ones. Tools like Webpack automatically handle these chunks, reducing the amount of JavaScript the browser loads initially.

const ContactForm = lazy(() => import(/* webpackChunkName: "contact-form" */ "./ContactForm"));

Webpack will name the chunk contact-form.js, making debugging and performance monitoring easier.

Lazy Loading in Server-Side Rendered React Apps

For server-side rendering (SSR) with lazy loading, you need libraries like loadable-components because React.lazy() does not work on the server.

npm install @loadable/component

import loadable from "@loadable/component";

const LazyComponent = loadable(() => import("./LazyComponent"), {
  fallback: <div>Loading...</div>,
});

function App() {
  return <LazyComponent />;
}

This method ensures that server-rendered pages can still benefit from lazy loading without breaking SSR functionality.

React lazy loading is an essential technique for optimizing performance. It helps reduce initial load times, improves user experience, and minimizes resource usage.

Learn React for Free
Start learning now
button icon
To advance beyond this tutorial and learn React by doing, try the interactive experience of Mimo. Whether you're starting from scratch or brushing up your coding skills, Mimo helps you take your coding journey above and beyond.

Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.

You can code, too.

© 2025 Mimo GmbH