How to Implement Lazy Loading in React
Lazy loading is a powerful optimization technique in React that
improves application performance by loading components only when they
are actually needed. This article provides a straightforward,
step-by-step guide on how to implement lazy loading in React using
React.lazy and Suspense, along with practical
code examples for both individual components and route-based code
splitting.
Understanding React.lazy and Suspense
React provides built-in support for lazy loading through
React.lazy() and the Suspense component.
React.lazy(): A function that lets you render a dynamic import as a regular component. It automatically bundles the component into a separate chunk during build time.Suspense: A wrapper component that allows you to show a fallback UI (like a loading spinner or text) while the lazy-loaded component is being fetched.
Implementing Component-Level Lazy Loading
To lazy load a component, you replace your standard static import
with a dynamic import wrapped inside React.lazy(). You must
then render that component inside a <Suspense>
block.
Here is a basic example:
import React, { Suspense } from 'react';
// Dynamically import the heavy component
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
function App() {
return (
<div>
<h1>My React Application</h1>
{/* Wrap the lazy component in Suspense and provide a fallback */}
<Suspense fallback={<div>Loading component...</div>}>
<HeavyComponent />
</Suspense>
</div>
);
}
export default App;In this setup, HeavyComponent will not be loaded when
the user first visits the page. Instead, the browser will fetch its
bundle only when App renders, displaying the “Loading
component…” message in the meantime.
Implementing Route-Based Lazy Loading
One of the best places to use lazy loading is at the router level. This ensures that users only download the code for the specific page they are currently visiting, greatly reducing the initial loading time of your website.
Here is how you can implement route-based lazy loading using React Router:
import React, { Suspense } from 'react';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
// Lazy load the page components
const Home = React.lazy(() => import('./pages/Home'));
const About = React.lazy(() => import('./pages/About'));
const Contact = React.lazy(() => import('./pages/Contact'));
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link> |
<Link to="/about">About</Link> |
<Link to="/contact">Contact</Link>
</nav>
{/* Wrap all routes in Suspense to handle loading transitions */}
<Suspense fallback={<div>Loading page...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Suspense>
</Router>
);
}
export default App;Key Considerations
To ensure a smooth user experience when implementing lazy loading, keep the following best practices in mind:
- Default Exports Only:
React.lazycurrently only supports default exports. If the component you want to import uses named exports, you must re-export it as a default export in an intermediary file. - Error Boundaries: If a lazy-loaded component fails
to load (due to a network error, for example), your app might crash.
Wrap your
<Suspense>components in an Error Boundary to handle these failures gracefully. - Selective Loading: Do not lazy load every component. Focus on large third-party libraries, complex components (like charts or rich text editors), and page-level routes.