javascriptreactjsnext.jsyoutube-apinextjs-image

What is the best way to have a fallback image in NextJS?


Recently, I have been working on a project in NextJS which uses the YoutubeAPI to fetch video information, including thumbnail URLs.

The thumbnail URL for a full resolution image looks like this: https://i.ytimg.com/vi/${videoId}/maxresdefault.jpg

However, sometimes YouTube fails to generate a full-resolution image, and in that case, the image is not displayed on my webpage.

In the case that the image with the URL https://i.ytimg.com/vi/${videoId}/maxresdefault.jpg does not exist I wish to use another URL like https://i.ytimg.com/vi/${videoId}/hqdefault.jpg

What is the best way to handle this with next/image?


Solution

  • These answers were helpful but there's a way to achieve this without needing to pass a key each time by taking advantage of the useEffect hook:

    useEffect(() => {
        set_imgSrc(src);
    }, [src]);
    

    Additionally, the onError event doesn't seem to trigger for certain images (I believe layout='fill' doesn't trigger it in certain scenarios), for those cases I've been using the onLoadingComplete and then I check if the width of the image is 0

    onLoadingComplete={(result) => {
        if (result.naturalWidth === 0) {  // Broken image
            set_imgSrc(fallbackSrc);
        }
    }}
    

    Full code:

    import Image from "next/image";
    import { useEffect, useState } from "react";
    
    export default function ImageFallback({ src, fallbackSrc, ...rest }) {
      const [imgSrc, set_imgSrc] = useState(src);
    
      useEffect(() => {
        set_imgSrc(src);
      }, [src]);
    
      return (
        <Image
          {...rest}
          src={imgSrc}
          onLoadingComplete={(result) => {
            if (result.naturalWidth === 0) {
              // Broken image
              set_imgSrc(fallbackSrc);
            }
          }}
          onError={() => {
            set_imgSrc(fallbackSrc);
          }}
        />
      );
    }