React Image Lazy Loading Component

Today we’ll be creating a pretty cool image lazy loading React component inspired by Polymer’s (Link) iron-image component.

If you want to know more about Polymer and its place in the JavaScript framework ecosystem I wrote a blog post about that (Link)

Polymer’s iron-image component is really simple and straight forward (as will our React counterpart be).
What it does is you give it a src of the image you want to be displayed and a src of a placeholder image to show while it’s loading the main image in the background and when it’s done loading it fades in the main image over the placeholder image.

Easy peasy.

The trick Polymer devs use with iron-image is they make a copy of the image they want to display and scale it down to 1% of its width and height and they use that scaled down image as the placeholder image. 
What this does is display a sort of blurred main image while it’s loading and when the main image is done loading the fade in effect makes it look like that blurred image is sharpening into the main image. Cool!

Now that we know what we’re building we can get started on react-iron-image.

You can find code for react-iron-image on my Github page (Link)

You can ignore most of the code in App.js since it’s just a container for our IronImage component and largely unimportant.
The 3 lines of code that we actually do care about are:

import image from './iron-image-small.jpg';
...
const hdUrl = 'https://images.unsplash.com/photo-1478562853135-c3c9e3ef7905';
...
<IronImage srcPreload={image} srcLoaded={hdUrl} />

The first line imports the scaled down image that we’ll be using as placeholder until our main image is ready to be displayed.

The second line is the URL of the full size main image.

I found the image we’ll be using on unsplash.com (Link) and a big shout out to Austin Neill (Link) for providing such awesome pics!

The third line is our React IronImage component. Notice how we’re passing in the preload src and full size image src as props.

Now let’s take a look at our IronImage component code.

As you can see the component is really nothing special, it’s simple and straightforward. Let’s go through the logic.

First we import the React stuff and styles for our component (“IronImage.css” — we’ll take a look at that after we go through the logic) then we create the component by extending React’s component.

In our constructor call we initialize ironImageHd we need it to hold a reference of the element in which we’re going to render our main image when it’s done loading.

Let’s skip the code in componentDidMount for now and go to our render function.
Our render function displays 2 images

I use div’s with background-image’s because I think they’re easier to work with and are more consistent than img tags but you can get the same functionality with img tags as well

We get the preload image as a prop and set the background of the preload element to display it. Now we’re displaying the blurred version of our main image. Neat.

The second image is a bit different. 
Since our main image isn’t ready to be displayed immediately we can’t set the background to the full size image.
What we can do is get the reference to the element (ref={...}) and when we have the full size image we can then set the background image and fade it in.

If you want to know more about Reacts ‘ref’ you can find more info here Link

Now for the fun part!
In our componentDidMount function we create a new Image; we set its src to the full size image src that we got from props and we add a callback for when the image is done loading.
After the image is done loading we set the background image of ironImageHd element and we tell it to fade in using css; now is a good time to take a look at our “IronImage.css” file:

Again, nothing special, we position the full size image over the preload image and stretch them to fit the container. 
We hide the full size image div so the placeholder is visible until it’s done loading, after it’s done loading we up it’s opacity to 1 and transition: opacity 1s ease; does all of the work of fading in (‘sharpening’) the image for us aaaaaaaaaaaand WE’RE DONE!

And there you have it! We have a cool image lazy loading React component.
The Really cool thing about this component is that it lends itself to improvements and new functionality perfectly. 
You can try implementing new animations instead of the default fade in or triggering the image load when certain conditions are met, the possibilities are endless!

This code is licensed under the DWFYW (Do Whatever the F You Want) license so go crazy baby gurl, you deserve it!