feat: add ProductImage component with onError fallback
This commit is contained in:
@@ -0,0 +1,42 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
|
const PLACEHOLDER = '/images/product-placeholder.svg';
|
||||||
|
|
||||||
|
interface ProductImageProps {
|
||||||
|
src?: string | null;
|
||||||
|
alt: string;
|
||||||
|
className?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
loading?: 'lazy' | 'eager';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ProductImage({ src, alt, className, width, height, loading }: ProductImageProps) {
|
||||||
|
const hasErrored = useRef(false);
|
||||||
|
|
||||||
|
// Reset the loop guard whenever src changes (e.g. navigating between products)
|
||||||
|
useEffect(() => {
|
||||||
|
hasErrored.current = false;
|
||||||
|
}, [src]);
|
||||||
|
|
||||||
|
function handleError(e: React.SyntheticEvent<HTMLImageElement>) {
|
||||||
|
if (hasErrored.current) return;
|
||||||
|
hasErrored.current = true;
|
||||||
|
e.currentTarget.src = PLACEHOLDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
// eslint-disable-next-line @next/next/no-img-element
|
||||||
|
<img
|
||||||
|
src={src ?? PLACEHOLDER}
|
||||||
|
alt={alt}
|
||||||
|
className={className}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
loading={loading}
|
||||||
|
onError={handleError}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user