React Lazy Load

yarn add react-lazyload

Usage

import React, { useState, useEffect, useRef } from "react";
import LazyLoad from "react-lazyload";
import classNames from "classnames";
import PropTypes from "prop-types";

const debug = require("debug")("app:LazyImage");

LazyImage.propTypes = {
  src: PropTypes.string,
  height: PropTypes.string,
  width: PropTypes.string,
  alt: PropTypes.string,
  className: PropTypes.string,
  imgCls: PropTypes.string,
  style: PropTypes.object,
  darkMode: PropTypes.bool,
};

export default function LazyImage(props) {
  const { src, height, width, alt, className, darkMode, imgCls } = props;

  return (
    <div className={`${className}`} style={props.style}>
      <LazyLoad
        classNamePrefix="relative w-full "
        offset={300}
        height={height}
        width={width}
        overflow
        resize
        once
      >
        <MyImage
          src={src}
          height={height}
          width={width}
          alt={alt}
          darkMode={darkMode}
          imgCls={imgCls}
        />
      </LazyLoad>
    </div>
  );
}

//Must be in seperate component so can listen to when the LazyLoad mounts it
MyImage.propTypes = {
  src: PropTypes.string,
  height: PropTypes.string,
  width: PropTypes.string,
  alt: PropTypes.string,
  style: PropTypes.object,
  darkMode: PropTypes.bool,
  imgCls: PropTypes.string,
};

function MyImage(props) {
  const { src, height, width, alt, style, darkMode, imgCls } = props;
  const [loaded, setLoaded] = useState(false);
  const imgR = useRef(null);

  useEffect(() => {
    const img = imgR.current;
    function setLoadedTrue() {
      setLoaded(true);
    }

    if (img) {
      img.addEventListener("load", setLoadedTrue);

      if (img.complete) {
        //if already loaded
        setLoaded(true);
      }

      return () => img.removeEventListener("load", setLoadedTrue);
    }
  }, []);

  const cls = classNames({
    "absolute w-full h-full left-0 top-0 right-0 bottom-0 z-10 transition-opacity duration-500 ease-in-out ": true,
    "opacity-0": loaded,
    "opacity-100": !loaded,
    "bg-pureBlack": darkMode,
    "bg-white": !darkMode,
  });

  return (
    <>
      <div className={cls} />
      <img
        src={src}
        height={height}
        width={width}
        alt={alt}
        ref={imgR}
        style={style}
        className={imgCls}
      />
    </>
  );
}

Last updated