DEV Community

Cover image for Configure Fallback Images in React and Next.js
Elisabeth Leonhardt
Elisabeth Leonhardt

Posted on • Updated on

Configure Fallback Images in React and Next.js

Why did I need a fallback?

Recently at work, I had to display lots of user data with images on the website I was building. I was getting all the data from an API and it was just a matter of putting things on the screen...

Except that, in some cases, the image for the user didn't exist anymore. So although I had a src for my image tag, there was no image and the page would just show the alternative text I provided. Here you can see a broken src on the left and a normal image on the right:

broken src on the left, normal image on the right

This looked horrible, so I was asked to put a fallback image whenever there was a problem with the source.

Fallback images in React

For React, the solution is only one additional line to the code you would normally write. Let's take a look:

import fallback from "../public/fallback-image.png";

function ImageWithFallback({ src, alt, fallBackSrc = fallback.src }) {
  return (
    <div style={{ border: "1px solid black", height: "50vh" }}>
      <img
        src={src}
        alt={alt}
        style={{ height: "100%", aspectRatio: "1 / 1", objectFit: "cover" }}
        onError={(e) => (e.currentTarget.src = fallBackSrc)}
      />
    </div>
  );
}

export default ImageWithFallback;

Enter fullscreen mode Exit fullscreen mode

Div and styling are only there for illustration purposes. We can see that this doesn't differ from the regular image tag we already know. The magic happens in the onError callback function, which gets fired as soon as there is a problem with the src. When this happens, our src will be replaced by our fallback image and we can go take a break. ☕

Showing a fallback image instead of the alternative text

Fallback images with optimized Images in Next.js

In my case, I was using the Image-tag from Next.js to take advantage of lazy loading and image optimization. When I tried to use the same onError function with Next.js, the fallback image would never show! Therefore, I created a piece of state so I could rerender the component in case of an error:

import fallback from "../public/fallback-image.png";
import Image from "next/image";
import { useState } from "react";

function OptimizedImageWithFallback({ src, alt, fallBackSrc = fallback.src }) {
  const [imageError, setImageError] = useState(false);
  return (
    <div
      style={{
        border: "1px solid black",
        position: "relative",
      }}
    >
      <Image
        src={imageError ? fallBackSrc : src }
        alt={alt}
        width={500}
        height={500}
        objectFit='cover'
        onError={() => setImageError(true)}
      />
    </div>
  );
}

export default OptimizedImageWithFallback;
Enter fullscreen mode Exit fullscreen mode

The outer div is a requirement of the next image tag and again for some styling. The onError function in this case just changes the error state to true, causing a rerender and changing the src to fallBackSrc.

That's it! I hope it helped you out! See you next time 😀

Discussion (3)

Collapse
salmanhpt profile image
salmanhpt

do you think this will also solve the image indexing issue that is faced by many.

I have yet to see a Next/Image generated URL to be indexed by google, like this:

www.example.com/_next/image?url=%2Fimages%2Fhome%2FDog-image-1.jpg&w=384&q=100

Collapse
dineufeld profile image
Dimitri Neufeld • Edited on

found conditional logic issue, it should be
src={imageError ? fallBackSrc : src}
....

Collapse
elisabethleonhardt profile image
Elisabeth Leonhardt Author

That's absolutely correct! Thank you for pointing this out - I already the example in the article 😀