главная/React JS компонент lazyload image (ленивая загрузка изображений)
Компонент ленивой загрузки на React js

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')
);