React JS компонент lazyload image (ленивая загрузка изображений)
Напишем компонент ленивой загрузки изображения (lazyload image).
- useState() — хук для создания значения с отслеживанием состояния, которое указывает, было ли загружено изображение.
- useEffect() — хук для проверки если HTMLImageElement.prototype содержит ‘loading’ тем самым проверяя, поддерживается ли ленивая загрузка изначально. Если нет создаем новый IntersectionObserver и используем IntersectionObserver.observer() для для наблюдения за тэгом img. Используем return для зачистки когда компонент совершил unmount.
- useCallback() — для мемоизации колбэк функции для IntersectionObserver. Этот колбэк будет апдейтить isLoaded стэйт и использовать IntersectionObserver.disconnect() для дисконекта сущности IntersectionObserver.
- useRef() — хук для создания двух связей. Один для img элемента, а второй для сущности IntersectionObserver
- В конце выводим тэг <img> с данными атрибутами. Применяем атрибут loading=’lazy’ если это необходимо. Используем isLoaded для определения значения атрибута src.
Код компонента ленивой загрузки — React Lazyload Image
const LazyLoadImage = ({
alt,
src,
className,
loadInitially = false,
observerOptions = { root: null, rootMargin: '220px 0px' },
...props
}) => {
const observerRef = React.useRef(null);
const imgRef = React.useRef(null);
const [isLoaded, setIsLoaded] = React.useState(loadInitially);
const observerCallback = React.useCallback(
entries => {
if (entries[0].isIntersecting) {
observerRef.current.disconnect();
setIsLoaded(true);
}
},
[observerRef]
);
React.useEffect(() => {
if (loadInitially) return;
if ('loading' in HTMLImageElement.prototype) {
setIsLoaded(true);
return;
}
observerRef.current = new IntersectionObserver(
observerCallback,
observerOptions
);
observerRef.current.observe(imgRef.current);
return () => {
observerRef.current.disconnect();
};
}, []);
return (
<img
alt={alt}
src={isLoaded ? src : ''}
ref={imgRef}
className={className}
loading={loadInitially ? undefined : 'lazy'}
{...props}
/>
);
};
ReactDOM.render(
<LazyLoadImage
src="image url"
alt="alt text"
/>,
document.getElementById('root')
);