Open SheepTester opened 9 months ago
@SheepTester can you try sending a memoized callback for error? this (useCallback)[https://github.com/vercel/next.js/blob/fa32e32df47774c60a731553c447e1d4880bdd4b/packages/next/src/client/image-component.tsx#L229] has the onError dependency.
Ah, memoizing the callback fixes it, thanks! This fixes the issue I had in my project.
I suppose for such an easy fix, this issue could be closed, unless there's still interest in improving this?
i noticed this happening to myself in dev mode only in a library i'm working on: https://github.com/cloudinary-community/next-cloudinary/blob/main/next-cloudinary/src/components/CldImage/CldImage.tsx#L156
its not as much of a concern because it seems to only be reproducible in dev mode, however, i'm still seeing duplicate image requests come through, yet when similarly commenting out onError, it doesn't happen anymore
im currently using a callback (though certainly could be doing something wrong)
ive even tried simply passing back the simple instance from SheepTester's example above:
const handleError = useCallback(() => {}, []);
return (
<ResolvedImage
key={imgKey}
{...imageProps}
loader={loader}
onError={handleOnError}
ref={ref}
/>
);
yet still see the duplicate request
for sake of testing things, i commented out pretty much all other props (including the key) and only onError impacts this
one thing of note is the wrapper component only renders "once"
i think this is a bug ihave same issue with onError:
import NextImage from "next/image"; import placeholderImg from "@/assets/imgs/placeholder.png"; import { useCallback, useMemo } from "react"; export default function Image({ lazy, src, ...props }) { const memoizedSrc = useMemo(() => src, [src]); const handleError = useCallback((e) => { const img = e.target; if (img.src === placeholderImg.src) { return; } img.style = "object-fit: none; background: var(--color-light-3); max-height: 100%;"; img.src = placeholderImg.src; }, []); return ( <NextImage {...props} src={memoizedSrc} onError={handleError} priority={!lazy} loading={lazy ? "lazy" : "eager"} /> ); }
@colbyfayock
Link to the code that reproduces this issue
https://codesandbox.io/p/devbox/boring-wright-cf45dc
To Reproduce
onError
set) restarts every second, when there's a rerender due to a state change, while the right gif plays normally.onError={() => {}}
Current vs. Expected behavior
I expect the image to behave the same regardless of whether
onError
is set or not. However, due to theimg.src = img.src
line linked below, settingonError
has several side-effects (becauseimg.src = img.src
is not pure)onLoad
on every re-renderVerify canary release
Provide environment information
Which area(s) are affected? (Select all that apply)
Image optimization (next/image, next/legacy/image)
Additional context
I believe this is due to the following lines, introduced in #39824
https://github.com/vercel/next.js/blob/fa32e32df47774c60a731553c447e1d4880bdd4b/packages/next/src/client/image-component.tsx#L241-L247