DEV Community

Cover image for Lazy Loading Images in React for Better Performance
Muhammad Naufal
Muhammad Naufal

Posted on

Lazy Loading Images in React for Better Performance

In some cases, we need to load a list that contains a lot of images on a single page. Most of the images not even visible on the screen when it is loaded. We need to scroll down to see them. By default, when we open the page, the browser would load and request all the images on the page regardless if it’s visible on the viewport or not. That’s perfectly fine in some conditions, but when we have a lot of images that are not visible on the viewport and load all of them at the same time, that may lead to performance issues.

In that condition, it’s better to only load the images that appear on the viewport. It improves the performance cause the browser will postpone loading the images below the viewport until the user scrolls the page and reach the images.

Let’s Start

There are several ways to do lazy loading including a native way, but when I write this post, native lazy loading is only supported in Chromium-based browsers and Firefox. So for wider browsers support, we’re going to do lazy loading using react-lazyload, and styled-components for styling. You can start by installing these packages:

npm install --save react-lazyload styled-components

// or if you prefer yarn:

yarn add react-lazyload styled-components

Create LazyImage component

We’ll use this component when we want to lazy-load images.

The LazyImage component contains ImageWrapper, Placeholder, LazyLoad, and StyledImage. Anything inside LazyLoad would not load until it appears on the viewport, that’s why we put StyledImage inside it.

Placeholder is just an empty div with animation to indicate the image is still loading. When the image finally loaded then we call removePlaceholder to remove Placeholder from the DOM. I use refs to do that instead of updating the state to prevent unnecessary re-rendering. If you’re unfamiliar with refs in React, you can learn more about it here.

You can create shimmer or put spinner inside the Placeholder, but I just made it simple here with animated background. Set the Placeholder size the same as the image size so the transition will be smoother. In the example above, the size of Placeholder and StyledImage will follow the ImageWrapper size.

You might wanna use react-lazyload placeholder prop to put Placeholder like this:

<LazyLoad placeholder={<Placeholder />}>
  ...
</LazyLoad>

But when I tried that, the Placeholder would instantly disappear when it reaches the viewport as I scroll the page even though the image is still not fully loaded, hence I put it outside and manage it with onLoad and onError events.

Let’s Try It

In App.js, we’ll use dummy images from Picsum Photos to demonstrate and see how the LazyImage works.

It’s not recommended and considered as anti-pattern to use indexes for keys. I did that in this example just to make it simple and straightforward to focus on lazy loading.

When we run the App, it would look like this:

The Result

As you can see from the gif above, images not loaded until it appears on the viewport, which improves the performance and reduces bandwidth consumption. This method also works fine in Server Side Rendering.

You can still improve it by adding different rendered elements/style when an error happens or create fade-in animation when the image appears, I leave that for you to try.

I put the code on Codesandbox, you can try and play with it here.

I hope this post helps you! Thanks for reading!

Top comments (0)