TanStackT
TanStack15mo ago
3 replies
hurt-tomato

Re-render issue: Masonry Grid implementation in Next.js

Hello,

I've been facing this issue for a while now, I have a masonry grid that renders images from an external source, and when the image source is broken, I set the source to a default image that shows the image is broken.

Now every time I scroll, the image starts loading again (because I have a shimmer effect flash for a sec), and it doesn't have to be a big scroll, it could be as little as little as a few pixels (~10px).

On Firefox - All the images reload
On Chrome (or Chromium based browsers) - Just the broken images load again

Here is the code to the customized next/image component I'm using below;

export const CustomNextImage = React.memo(
  ({ src, alt, onError, onLoaded, hasError, ...rest }: NextImageProps) => {
    const { theme } = useTheme();
    const [URL, setURL] = useState<string>(src);

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

    const handleLoad = useCallback(() => {
      onLoaded && onLoaded();
    }, [onLoaded]);

    const handleError = useCallback(() => {
      setURL("/broken.png");
    }, []);

    const MemoizedURL = useMemo(() => URL, [URL]);

    if (!MemoizedURL || MemoizedURL === "self" || !isValidImageURL(MemoizedURL)) return null;

    return (
      <div className="w-full h-full bg-background">
        <Image
          draggable={false}
          {...rest}
          src={MemoizedURL}
          alt={alt}
          fetchPriority="high"
          decoding="async"
          sizes="100vw"
          width={100}
          height={100}
          loading="lazy"
          placeholder={`data:image/svg+xml;base64,${toBase64(
            shimmer(theme as "light" | "dark")
          )}`}
          quality={100}
          onError={handleError}
        />
      </div>
    );
  }
);


Can anyone help me understand what might be going on?
Thanks
Was this page helpful?