Handling image loading and error state in Next.js
Tags: react, nextjs, javascript, webdev
Published: 2021-11-17 10:16:58

### [How to create a loading and error state placeholder for images?](https://carlogino.cc/blog/next-image-state-handling)


> ### TL;DR
>
> Check the full code [here](https://gist.github.com/codegino/b9ed69fec8495c5024ef925c432bf1f2)


### Long version
<br />


#### Creating a basic image

`next/image` provides an easy way to create an image.

```jsx
import Image from 'next/image'

<Image src="https://i.imgur.com/gf3TZMr.jpeg" alt="Some alt text" />
```

However, we still need to configure some properties to cater to our specific needs, such as:
- A placeholder when loading
- An error placeholder when the image fails to load

<br />

The GIF below shows what a user will see for an image loaded using a slow internet connection.

<Img height={688} width={792} src="https://media2.giphy.com/media/mgOpxkjm3zjT2Utg5Q/giphy.gif"/>

It gives the impression that something is wrong with our app.

<br />

#### How to handle the loading state?

Simply adding the `placeholder` and `blurDataURL` will do the trick.

```jsx
<Image
  src="https://i.imgur.com/gf3TZMr.jpeg"
  placeholder="blur"
  blurDataURL="/assets/image-placeholder.png"
/>
```

The code will yield the following result:

<Img height={688} width={792} src="https://media2.giphy.com/media/nNsPF6B8EjQODCbqNM/giphy.gif"/>

There's a brief delay before the placeholder is loaded
because even the placeholder image needs to be fetched from the server.

> If we need to make sure that there's an immediate placeholder to the image,
> refer to this guide on [how to create a dynamic image placeholder](https://dev.to/codegino/dynamic-image-placeholder-in-nextjs-5052)

The good thing is that once the placeholder image is loaded, all other images that use the same asset
will display the placeholder immediately.

<Img height={688} width={792} src="https://media2.giphy.com/media/p1yrnptxP3GEXKV02B/giphy.gif"/>

<br />

### What happens if there's an error when loading the image

One possibility is that the user will stare at the placeholder for eternity.

<Img height={612} width={788} src="https://i.imgur.com/0RJSScx.png" />

<br />

Or this sadder version which shows the `alt` and much space.

<Img height={612} width={788} src="https://i.imgur.com/WHIrNTn.png" />


*It is not fun to see too much unnecessary space, is it?*

<br />
<br />

#### How to display another image during an error state?

We can replace the value of `src` with the path to `error image` in the `onError` callback when an error happens.

```jsx
const [src, setSrc] = React.useState('https://i.imgur.com/gf3TZMr.jpeg');

<Image
  {...props}
  src={src}
  placeholder="blur"
  blurDataURL="/assets/image-placeholder.png"
  onError={() => setSrc('/assets/image-error.png')}
/>
```

<Img height={688} width={792} src="https://media2.giphy.com/media/GEtkLddj2L7lk6tqhU/giphy.gif"/>

*I believe it's much better.*

<br />

### Putting all the code together

To make the behavior easy to replicate, we can create a custom image component.

```jsx
function CustomImage({alt, ...props}) {
  const [src, setSrc] = React.useState(props.src);

  return (
    <Image
      {...props}
      src={src}
      alt={alt} // To fix lint warning 
      onError={() => setSrc('/assets/image-error.png')}
      placeholder="blur"
      blurDataURL="/assets/image-placeholder.png"
    />
  );
}
```

<br />

## Conclusion
When a web application displays many images, it is a good idea to give immediate feedback to the user of what is happening. One way to address this is to use an alternate image to show the current state of an image.

### If you find this useful and you want to support me

<a href="https://www.buymeacoffee.com/codegino" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="37" width="174"></a>