Next.js Discord

Discord Forum

<Image> infinite loop on broken link

Answered
berkserbet posted this in #help-forum
Open in Discord
My site keeps requesting the image even when it gets a 404. I am trying to make it grab another image as backup on error. But it never requests the backup image.

This is what my component looks like:
<Image
  loader={imageKitLoader}
  src={image ? image : placeholderImage}
  onError={onImageError} 
  className="w-full rounded-box object-contain"
  width={480}
  height={480} 
  alt="Item Picture"
/>


And:
const placeholderImage = "https://....."
const onImageError = (e: any) => {
  e.target.src = placeholderImage
}
Answered by Northeast Congo Lion
export default function LocalImage = (props) => {

  const { src, fallbackSrc, className, ...rest } = props;
  
  const [ imgSrc, setImgSrc ] = useState(src); 
  
  if (!src) return <></>

  ..imgLoaderCode etc
  
  return (
    <Image
      onError={(e) => setImgSrc(fallbackSrc)}
      loader={imageKitLoader}
      src={imgSrc}
      {...rest}
    />
  );
}
View full answer

56 Replies

Also, this is on the client side
Northeast Congo Lion
where is loader function? pls show code
@Northeast Congo Lion where is `loader` function? pls show code
Thanks!

const imageKitLoader = ({
  src,
  width,
  quality,
}: {
  src: string;
  width: number;
  quality?: number;
}) => {
  if (src[0] === '/') src = src.slice(1);
  const params = [`w-${width}`];
  if (quality) {
    params.push(`q-${quality}`);
  }
  const paramsString = params.join(',');
  var urlEndpoint = 'https://ik.imagekit.io/...';
  if (urlEndpoint[urlEndpoint.length - 1] === '/')
    urlEndpoint = urlEndpoint.substring(0, urlEndpoint.length - 1);

  if (src.includes("redd.it")) {
    return `${urlEndpoint}/r/${src.split("/").pop()}?tr=${paramsString}`;
  } else if (src.includes("postimg")) {
    return `${urlEndpoint}/postimg/${src.split(".cc/").pop()}?tr=${paramsString}`;
  } else {
    return `https://...`
  }
};
Northeast Congo Lion
and inside console
what is the url it is requesting
show me 404 log
@Northeast Congo Lion show me 404 log
Failed to load resource: the server responded with a status of 404 ()
Just tons of that
Northeast Congo Lion
it should show a url
of what it is trying to request, failing that check network tab
Northeast Congo Lion
expected
Non existing url
I know
Northeast Congo Lion
so u want to see if 404, use placeholder
But I want it to stop after 1 404 and use backup
Yup!
Northeast Congo Lion
ok idk if u can stop after 1 404
1 sec
could you maybe try onLoad?
not 100% how u can update image src on error
unless you create global component which uses placeholder img
and onError(() => return <FallBackImg /> )
I have the onError
Northeast Congo Lion
can u try above return component?
see if that works
Yeah!
@Northeast Congo Lion see if that works
That goes in the <Image> right? Sorry new to this
@berkserbet That goes in the <Image> right? Sorry new to this
Northeast Congo Lion
yup
or u can
put it in ur
const onImageError = (e: any) => {
  return <FallbackImg />
}
I now have:
  const onImageError = (e: any) => {
    e.target.src = placeholderImage
  }
Northeast Congo Lion
yeah i dont think this is right way to update nextjs image component
what i would be doing which is easier:

return (
   {
     (image && image.src) && <Image /> 
   }
);
or can even do image?.src && <Image />
The infinite loop is gone with:
  const onImageError = (e: any) => {
    <Image
      loader={imageKitLoader}
      src={placeholderImage}
      className="w-full rounded-box object-contain"
      width={480}
      height={480} 
      alt="Item Picture"
    />
  }
But not showing placeholder
Northeast Congo Lion
kk
better way to do it actually
is for the image component u store imgSrc in state
The images on my site change every few mins
Northeast Congo Lion
no no
so on Error
u update state to placeholder value
what i would do is create a CustomImage wrapper
Northeast Congo Lion
export default function LocalImage = (props) => {

  const { src, fallbackSrc, className, ...rest } = props;
  
  const [ imgSrc, setImgSrc ] = useState(src); 
  
  if (!src) return <></>

  ..imgLoaderCode etc
  
  return (
    <Image
      onError={(e) => setImgSrc(fallbackSrc)}
      loader={imageKitLoader}
      src={imgSrc}
      {...rest}
    />
  );
}
Answer
Northeast Congo Lion
yea
something like that
then when u need image, instead of using <Image /> u use <LocalImage /> from now on
Got it, thank you!
@berkserbet Got it, thank you!
Northeast Congo Lion
is it working now?
Northeast Congo Lion
@berkserbet ?
Yup, sorry for the delay!
@berkserbet Yup, sorry for the delay!
Northeast Congo Lion
can u mark as solved pls