Lazy loading in React

Learn about lazy loading in React and how/when to use it
profile
Akshay AvinashFirst published: 2020-10-05Last updated: 2025-06-25
lazy-loading-in-react

Overview

You may have come across the term- “lazy loading in React”, but most of you won’t be familiar with exactly what is lazy loading in React. Lazy loading is not a new concept. It has been available for quite some time. In essence, lazy loading means that a component or a part of code must get loaded when it is required. It is also referred to as code splitting and data fetching. Now, the next question is, how to do lazy loading in react​?

Talking about React specifically, it bundles the complete code and deploys all of it at the same time. Now, usually, that's not a bad idea, since React SPAs (Single page application) are quite small and do not affect the performance. But what if we have a gigantic application, like a content management system with a customer portal, admin portal etc. In such a case, it does not seem like a smart idea to load the complete application.

  • It will be a huge application and will cost a lot of unnecessary data transfer which can lead to slow loading of the website.
  • A customer login, will not have access to admin specific features, so loading it is a waste of memory and time.

In this post, I will try to explain the advantages of lazy loading in react and how to implement it in React.

Advantages

In situations where we know that certain code/features will not be accessible to all the users or the user does not access it frequently, it is best to load them when the user requests for it. This improves user experience as well as initial loading time.

For example, let's consider that our application has two sections, A and B. Size of A is 1 MB and its loading time is approximately 1 second. Size of B is also 1 MB and so its loading time is also 1 second. And we know that a user will access either of the sections, or a user accessing section A will rarely access section B and vice versa. If we were to load the complete application at the starting of our application, it would cost the user 2 MB of data and the loading time will also be 2 seconds. The user might not like to wait for 2 seconds or won't be happy that a site is costing them a lot of data. This can be improved and halved with proper lazy loading through lazy load react components.

Note: This is not the general case. Small single-page applications are usually in kbs.

Prerequisites

To follow this tutorial, you’ll need the following:

General instructions

  1. We will perform lazy loading in React with react suspense and without it.

  2. First of all, create the app using npm create-react-app

    1npm create-react-app my-app
  3. Now run the app by running following command in the project directory root

    1npm start
  4. The default react app will run in http://localhost:3000

  5. Let the directory structure be

    1|
    2|-src
    3|	|-components
    4|	|	|-Admin.js
    5|	|	|-Customer.js
    6|	|	|-Home.js
    7|	|-app.js
    8|-index.js
  6. Application will first render app.js which will have an input field. We will pass the input received as props to Home, and render Home.js. Based on props received, we will either render Admin or Customer.

Using React Suspense (React 16.6+)

From React 16.6+, react added React Suspense which performs lazy loading.

  1. In our Home.js, we will lazy load Admin and Customer
    1import React, { Suspense } from "react";
    2const Customer = React.lazy(() => import("./Customer.js"));
    3const Admin = React.lazy(() => import("./Admin.js"));
    4//Instead of regular import statements, we will use the above approach for lazy loading
    5export default (props) => {
    6if (props.user === "admin") {
    7return (
    8// fallback component is rendered until our main component is loaded
    9<Suspense fallback={<div>Loading</div>}>
    10<Admin />
    11</Suspense>
    12);
    13} else if (props.user === "customer") {
    14return (
    15<Suspense fallback={<div>Loading</div>}>
    16<Customer />
    17</Suspense>
    18);
    19} else {
    20return <div> Invalid User </div>;
    21}
    22};

Without React Suspense

When talking about react lazy loading, if you are working with React version prior to 16.6, you won't have the Suspense component. It is best to upgrade to the latest version and use Suspense. If you're not able to upgrade and still want this feature, it is still possible to create your own React Suspense component. I will be using Higher Order Component(HOC).

  • Our HOC (lazyLoader.js)
    1const lazyLoader = (importComp) => {
    2	return class extends React.Component {
    3		state: {
    4			component: null; //initializing state
    5		};
    6	//loading the component and setting it to state
    7	componentDidMount() {
    8		importComp().then((comp) => setState({ component: comp.default }));
    9	}
    10
    11	//rendering the component
    12	render() {
    13		const C = this.state.component;
    14		return C ? &#x3C;C {...this.props} /> : null;
    15	}
    16};
    17
    18};

export default lazyLoader; ```

  • Our calling component, in this case Home.js

    1import React from "react";
    2import { lazyLoader } from "./lazyLoader";
    3const Customer = lazyLoader(() => import("./Customer.js"));
    4const Admin = lazyLoader(() => import("./Admin.js"));
    5//Instead of regular import statements, we will use the above approach for lazy loading
    6export default (props) => {
    7if (props.user === "admin") {
    8return <Admin />;
    9} else if (props.user === "customer") {
    10return <Customer />;
    11} else {
    12return <div> Invalid User </div>;
    13}
    14};

    This was all about how to implement lazy loading in react, if you need the fallback feature, you can update HOC's render method where it is returning null. Instead of null, you can return your fallback component, and it can be passed as props too.

    Now our HOC would look like -

    1const lazyLoader = (importComp, fallback) => {
    2	return class extends React.Component {
    3		state = {
    4			component: null, //initializing state
    5		};
    6	//loading the component and setting it to state
    7	componentDidMount() {
    8		importComp().then((comp) => setState({ component: comp.default }));
    9	}
    10
    11	//rendering the component
    12	render() {
    13		const C = this.state.component;
    14		return C ? (
    15			&#x3C;C {...this.props} />
    16		) : fallback ? (
    17			fallback
    18		) : (
    19			&#x3C;div>loading&#x3C;/div>
    20		);
    21		// If component is not loaded then return fallback component, if fallback is not provided then use default loading
    22	}
    23};
    24
    25};
    26export default lazyLoader;