Fortune Ikechi Fortune Ikechi is a frontend engineer based in Rivers State, Nigeria. He is a student of the University of Port Harcourt. He is passionate about community and software engineering processes.

The top 5 lazy loading libraries for React in 2023

7 min read 2073

React Lazy Loading Libraries 2023

Editor’s note: This article was last updated 14 April 2023 to replace the deprecated gatsby-image package. 

Lazy loading is one way to optimize React applications to improve their load time. In this article, we’ll explore some of the best libraries for performing lazy loading in React. Let’s get started!

Jump ahead:

What is lazy loading, and why should you use it?

React applications are typically developed using images, videos, third-party packages and libraries, and API calls. Naturally, these things result in an increased bundle size as well as a longer first load time, thereby impacting the user experience.

Also known as code splitting or data fetching, lazy loading is a design method for optimizing web and mobile applications. With lazy loading, we delay loading parts of a webpage that aren’t immediately required, thereby improving the initial load time as well as the overall user experience.

In lazy loading, the app bundles are split into smaller chunks. The most important chunk is loaded first, while every secondary one is loaded only when it is needed.

How to implement lazy loading in React

Within the React ecosystem, there are a number of packages that help to optimize application performance through lazy loading. In this article, I’ll highlight some of the top choices for lazy loading React applications.

react-lazyload

react-lazyload is a package for lazy loading React components and images in React applications. To get started with react-lazyload, we install it as follows:

npm i react-lazyload

Now, we can lazy load our components with the following code:

import React from "react";
import LazyLoad from "react-lazyload";

export default function App() {
  return (
    <div className="list">
      <LazyLoad height={250} once>
        <img src="https://placedog.net/500/280" alt="dog" />
</LazyLoad>
      <LazyLoad height={250} once>
        <img src="https://placedog.net/500/300" alt="dog" />
      </LazyLoad>
      <LazyLoad height={250} offset={150}>
        <img src="https://placedog.net/500/300" alt="happy dog" />
      </LazyLoad>
    </div>
  );
}

In the code above, we wrap the LazyLoad component on whatever element we want to lazy load. We set the height of the element using the height attribute. With react-lazyload’s once property, once the content is displayed, it will no longer be managed by react-lazyload.

react-lazyload only has two event listeners for all the lazy-loaded components, thereby improving performance. It supports decorators and server-side rendering, and it also supports one-time lazy load and continuous lazy load mode, so you can choose the right approach depending on a component’s need.

However, react-lazyload might not be the perfect library for you. For example, depending on usage in your project, it can sometimes break your snapshot tests, and, if added to your project, it will add an extra DOM node.

To learn more about react-lazyload, you can check out the documentation. You can also check out a CodeSandbox example.

React Lazy Load Image Component

We can use React Lazy Load Image Component to lazy load both React components and images. React Lazy Load Image Component offers support for the Intersection Observer API, which determines when an element leaves and enters a viewport, and it’s also compatible with server-side rendering (SSR).

To use React Lazy Load Image Component, first install it via npm using the command below:

npm i --save react-lazy-load-image-component

You can see its usage in the code below:

import React from 'react';
import { LazyLoadImage } from 'react-lazy-load-image-component';

const ReactImage = ({ image }) => (
  <div>
    <LazyLoadImage
      alt={image.alt}
      src={image.src} />
    <span>{image.caption}</span>
  </div>
);

export default ReactImage;

In the code above, we import and wrap the LazyLoadImage component from React Lazy Load Image Component. Other image properties are passed as props.

React Lazy Load Image Component allows you to specify a custom placeholder for components, as well as events for beforeLoad and afterLoad. It is compatible with server-side rendered components and applications, and it is compatible with TypeScript declarations.

React Lazy Load Image Component comes built-in with visible effects, like blur and opacity transitions, and it features a customizable threshold.

Like the other lazy loading libraries, React Lazy Load Image Component has some downsides. For example, React Lazy Load Image Component loads all the images that are visible in the viewport at once, meaning if you have a gallery of images, then all the images will be loaded on the visible part of your webpage.

In addition, effects don’t work. To make effects work using this package, you’d need to import effect CSS, like in the docs. Finally, the React setState Hook can only work on mounted or mounting components. You can read more about React Lazy Load Image Component in the documentation.

React Lazy Load

According to its documentation, React Lazy Load is an easy-to-use React component that helps you defer loading content in a predictable way. It features an automatic component inside a scrolling container, like a scrollbar.

Install React Lazy Load as follows:

npm install --save react-lazy-load

To load a component using React Lazy Load, you’d wrap the component elements in a LazyLoad component:

import React from 'react';
import LazyLoad from 'react-lazy-load';

const App = () => {
  <div>
    List of cat images
    <div className="filler" />
    <LazyLoad height={500} offsetVertical={200}>
      <img src='http://placekitten.com/200/300' alt='cat' />
    </LazyLoad>    
    <LazyLoad height={500} offsetTop={200}>
      <img src='http://placekitten.com/200/300' alt='cat' />
    </LazyLoad>
    <div className="filler" />
    <LazyLoad height={480} offsetHorizontal={50}>
      <img src='http://placekitten.com/200/300' alt='cat' />
    </LazyLoad>
    <div className="filler" />
    <LazyLoad height={500} offsetTop={200}>
      <img src='http://placekitten.com/200/300' alt='cat' />
    </LazyLoad>
    <div className="filler" />
    <LazyLoad height={480} offsetHorizontal={50}>
      <img src='http://placekitten.com/200/300' alt='cat' />
    </LazyLoad>
    <div className="filler" />

Similar to most lazy loading libraries for React, React Lazy Load uses the LazyLoad component to determine which elements to lazy load.



React Lazy Load is fast, offers built-in support for IE8+ as well as debounce functions, and has a small bundle size of only 6kb minified compared to the others. However, keep in mind that it requires you to wrap each optimizable component and element using LazyLoad.

You can learn more about React Lazy Load here.

gatsby-plugin-image

gatsby-plugin-image helps you to produce responsive images in multiple sizes and formats, which you can easily add to a website. To help lazy load images for your website, it features advanced image loading capabilities.

To use gatsby-plugin-image, install it as follows:

npm install gatsby-plugin-image

gatsby-plugin-image requires gatsby-plugin-sharp; you should also install gatsby-transformer-sharp if you’re using dynamic images and gatsby-source-filesystem if you’re using static images:

npm install gatsby-plugin-sharp gatsby-source-filesystem gatsby-transformer-sharp

Add it to your Gatsby config file using the code below:

module.exports = {
  plugins: [
    `gatsby-plugin-image`,
    `gatsby-plugin-sharp`,
    `gatsby-transformer-sharp`,
  ],
}

There are two components from gatsby-plugin-image used to render images, one for static images and one for dynamic images. If you’re rendering an image that will be the same each time the component is rendered, then use StaticImage, like so:

import { StaticImage } from "gatsby-plugin-image"

export function Dino() {
  return <StaticImage src="../images/mycat.png" alt="A Cat" />
}

For a remote image, use the following:

import { StaticImage } from "gatsby-plugin-image"

export function Kitten() {
  return <StaticImage src="https://kitten.com/800/600" alt="A kitten" />
}

The component accepts configurations like width, height, and layout.

To render dynamic images, where the images will change at different times, you can load them via GraphQL and display them using the GatsbyImage component as follows:

import { graphql } from "gatsby"
import { GatsbyImage, getImage } from "gatsby-plugin-image"

function Article({ data }) {
  const image = getImage(data.article.avatar)
  return (
    <section>
      <h2&gt;{data.article.title}</h2>
      <GatsbyImage image={image} alt={data.article.author} />
      <p>{data.article.body}</p>
    </section>
  )
}

export const pageQuery = graphql`
  query {
    article(id: { eq: $Id }) {
      title
      body
      author
      avatar {
        childImageSharp {
          gatsbyImageData(
            width: 200
            placeholder: BLURRED
            formats: [AUTO, WEBP, AVIF]
          )
        }
      }
    }
  }

For images with fixed height and width, you can optimize gatsby-plugin-image. It’s fast, automatically lazy loads images, and can be optimized for images that stretch beyond the container.

Despite being highly optimized, gatsby-plugin-image has some downsides. For example, it struggles with non-Gatsby applications, and it can also be difficult for anyone without a basic understanding of GraphQL to use.

uselazy

uselazy is a React library for lazy loading and code splitting React components and images. uselazy handles both dynamic and named imports. Like most of the other libraries, you can install uselazy by using a package manager as follows:

npm install uselazy

Or, using Yarn:

yarn add uselazy

The code snippet below shows an example of using uselazy:

/// navbar.jsx

import React from 'react';

const Navbar = () => <p> React is awesome </p>

export default Navbar;


/// Menu.js

import React from 'react';

export const Menu = () = <h2> This is a menu page </h2>


/// App.js

import React, { useState } from 'react';
import useLazy from 'uselazy';

const imports = [() => import('./Navbar'), () => import('./Menu')];

const App = () => {
   const [shouldImport, setShouldImport] = useState(false);
   const { isLoading, result: Components } = useLazy(
      useMemo(() => imports, []),
      shouldImport,
  );

 return (
    <div>
      <h1>I'm very lazy </h1>
      <button onClick={() => setShouldImport(!shouldImport)}>Click menu</button>

      {isLoading && <span>some spinner</span>}

      {Components && Components.map(Component => <Component />)}
    </div>
  );
};

In the code above, uselazy preserves the identity of the imports and adds them as dependencies of the useEffect Hook inside of uselazy.

Some benefits of using uselazy in your React application include built-in support for dynamic and named imports as well as a very small bundle size of 31kb. You can learn more about uselazy in the official documentation.

React lazy and <Suspense>

As of React v16.6+, React offers built-in support for lazy loading using the lazy and <Suspense> components. We can use lazy to declare a lazy-loaded React component.

The components are rendered as users navigate through the app. React.lazy() accepts a function as an argument, which in turn, calls the dynamic import() in its body.

Typically, you’ll import a component with the static import:

import ExampleComponent from './ExampleComponent.js';

const App = () => (
    <div>
      <ExampleComponent />
    </div>
)

To delay loading this component’s code until it’s rendered for the first time, the code above is replaced with the following:

import { lazy } from 'react';

const ExampleComponent = lazy(() => import('./ExampleComponent.js'));

const App = () => (
    <div>
      <ExampleComponent />
    </div>
)

Now, the component’s code is loaded on demand. Because the components are loaded on demand, you need to specify what should be displayed while it is loading. Here, React.Suspense comes in. To provide a fallback, you wrap the lazy-loaded component or any of its parents into a <Suspense> boundary:

import { lazy, Suspense } from 'react';

const ExampleComponent = lazy(() => import('./ExampleComponent.js'));

const App = () => (
    <Suspense fallback={<div>Loading ...</div>}>
      <ExampleComponent />
    </Suspense>
)

The code above for ExampleComponent won’t be loaded until a user requests it. If ExampleComponent hasn’t loaded yet, Loading ... will be shown to the user in its place.

Conclusion

In today’s competitive development environment, optimizing your application’s performance is crucial. In this article, we’ve reviewed the performance benefits of lazy loading your React applications. We’ve also considered several libraries that make it easier than ever before to speed up the performance of your React app and improve the overall user experience.

Libraries like gatsby-plugin-image and react-lazyload are better suited for lazy loading image gallery applications, while other libraries, like uselazy, are better suited for components and React projects with a lot of dynamic and named imports.


More great articles from LogRocket:


With the Intersection Observer, libraries like React Lazy Load Image Component are ideal for TypeScript focused projects. However, it will struggle with performance in a gallery application since it loads all the images at the same time.

I hope you enjoyed this article, and be sure to leave a comment if you have any questions. Happy coding!

Get set up with LogRocket's modern React error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.
  3. $ npm i --save logrocket 

    // Code:

    import LogRocket from 'logrocket';
    LogRocket.init('app/id');
    Add to your HTML:

    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
  4. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • ngrx middleware
    • Vuex plugin
Get started now
Fortune Ikechi Fortune Ikechi is a frontend engineer based in Rivers State, Nigeria. He is a student of the University of Port Harcourt. He is passionate about community and software engineering processes.

One Reply to “The top 5 lazy loading libraries for React in…”

Leave a Reply