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:
gatsby-plugin-image
lazy
and <Suspense>
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.
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 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.
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.
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>{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 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.
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.
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.
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!
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ 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>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowOptimize search parameter handling in React and Next.js with nuqs for SEO-friendly, shareable URLs and a better user experience.
Learn how Remix enhances SSR performance, simplifies data fetching, and improves SEO compared to client-heavy React apps.
Explore Fullstory competitors, like LogRocket, to find the best product analytics tool for your digital experience.
Learn how to balance vibrant visuals with accessible, user-centered options like media queries, syntax, and minimized data use.
One Reply to "The top 5 lazy loading libraries for React in 2023"
Very informative article. Thanks