P
P
Pavel_Dorozhkin2020-12-28 21:36:40
JavaScript
Pavel_Dorozhkin, 2020-12-28 21:36:40

How to implement image substitution with native loading="lazy" support?

Hello everyone and Happy New Year)) I decided to make a component for lazy loading of images, for this I use react-intersection-observer. With its help, I track a picture that has not yet loaded and replace it with a loader. I wanted to do the same with native loading="lazy", but the trouble is that I don't understand what event the browser generates and when and how to track it. I started digging towards react-mutation-observer, but it did not work out. Perhaps everything is much simpler?)) Any ideas? Thank you in advance!

spoiler
export function LazyImage(props: LazyImageProps) {
  const {
    src,
    height,
    width,
    alt,
    styles,
    rootMargin = '0px',
    threshold = 0,
    loadImmediately
  } = props;

  const supportsNativeLazyLoading = 'loading' in HTMLImageElement.prototype;

  const { ref, inView } = useInView({
    rootMargin,
    threshold,
    triggerOnce: true
  });

  const [srcPath, setSrcPath] = useState(null);

  const preloadImage = (url: string) => {
    return new Promise((resolve, reject) => {
      const image = new Image();
      image.onload = resolve;
      image.onerror = reject;
      image.src = url;
    });
  };

  useEffect(() => {
    const checkPreloader = async () => {
      try {
        await preloadImage(src);
        // eslint-disable-next-line no-empty
      } catch (error) {
      } finally {
        setSrcPath(src);
      }
    };

    if (supportsNativeLazyLoading) {
      setSrcPath(src);
      return;
    }

    if (loadImmediately || inView) checkPreloader();
  }, [supportsNativeLazyLoading, src, loadImmediately, inView]);

  return srcPath ? (
    <S.Image
      loading={!loadImmediately ? 'lazy' : 'eager'}
      src={srcPath}
      alt={alt}
      height={height}
      width={width}
      css={styles}
    />
  ) : (
    <S.Preloader
      ref={!supportsNativeLazyLoading ? ref : null}
      height={height}
      width={width}
    />
  );
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alex, 2020-12-28
@Pavel_Dorozhkin

Images have a load event

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question