Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 1x 1x 1x 1x 29x 29x 29x 29x 23x 23x 23x 23x 23x 23x 29x 29x 29x 29x 29x 29x 29x 29x 29x 29x 29x 29x 29x 29x 29x 29x 29x 1x | import { useState, useEffect, useRef } from 'react';
import './LazyImage.scss';
export interface ILazyImage {
id?: string;
className?: string;
src?: string | null;
alt?: string;
onClick?: () => void;
}
const DEFAULT_LOGO = 'https://upload.wikimedia.org/wikipedia/commons/a/ac/No_image_available.svg';
const LazyImage: React.FC<ILazyImage> = ({ id, className, src = null, alt, onClick }) => {
const [loaded, setLoaded] = useState(false);
const [error, setError] = useState(false);
const imgRef = useRef<HTMLImageElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
observer.disconnect();
}
},
{ threshold: 0.1 }
);
if (imgRef.current) observer.observe(imgRef.current);
return () => observer.disconnect();
}, []);
return (
<>
{!loaded && <div className="lazy-placeholder" data-testid="lazy-placeholder" aria-hidden="true" />}
<img
id={id}
loading="lazy"
src={error || !src ? DEFAULT_LOGO : src}
alt={alt}
ref={imgRef}
onLoad={() => setLoaded(true)}
onError={() => setError(true)}
className={`img-fluid ${className} ${loaded ? 'lazyloaded' : 'lazyloading'}`}
onClick={onClick}
/>
</>
);
};
export default LazyImage;
|