Lazy Loading Images in React

ReactReactBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

In this lab, we will explore how to implement lazy loading images in a React application. Lazy loading improves page performance by delaying the loading of images until they are needed, reducing the initial load time and improving the user experience. We will use the Intersection Observer API and React hooks to create a reusable component that supports lazy loading images.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL react(("`React`")) -.-> react/FundamentalsGroup(["`Fundamentals`"]) react(("`React`")) -.-> react/AdvancedConceptsGroup(["`Advanced Concepts`"]) react(("`React`")) -.-> react/StateManagementGroup(["`State Management`"]) react/FundamentalsGroup -.-> react/conditional_render("`Conditional Rendering`") react/AdvancedConceptsGroup -.-> react/hooks("`React Hooks`") react/StateManagementGroup -.-> react/use_state_reducer("`Using useState and useReducer`") subgraph Lab Skills react/conditional_render -.-> lab-38350{{"`Lazy Loading Images in React`"}} react/hooks -.-> lab-38350{{"`Lazy Loading Images in React`"}} react/use_state_reducer -.-> lab-38350{{"`Lazy Loading Images in React`"}} end

Lazy-Loading Image

index.html and script.js have already been provided in the VM. In general, you only need to add code to script.js and style.css.

To render an image that supports lazy loading, follow these steps:

  1. Use the useState() hook to create a stateful value that indicates if the image has been loaded.
  2. Use the useEffect() hook to check if the HTMLImageElement.prototype contains 'loading'. This checks if lazy loading is supported natively. If not, create a new IntersectionObserver and use IntersectionObserver.observer() to observe the <img> element. Use the return value of the hook to clean up when the component unmounts.
  3. Use the useCallback() hook to memoize a callback function for the IntersectionObserver. This callback will update the isLoaded state variable and use IntersectionObserver.disconnect() to disconnect the IntersectionObserver instance.
  4. Use the useRef() hook to create two refs. One will hold the <img> element and the other the IntersectionObserver instance, if necessary.
  5. Finally, render the <img> element with the given attributes. Apply loading='lazy' to make it load lazily, if necessary. Use isLoaded to determine the value of the src attribute.

Here's an example implementation of these steps:

const LazyLoadImage = ({
  alt,
  src,
  className,
  loadInitially = false,
  observerOptions = { root: null, rootMargin: "200px 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}
    />
  );
};

To use this LazyLoadImage component, simply call it with the src and alt attributes of the image:

ReactDOM.createRoot(document.getElementById("root")).render(
  <LazyLoadImage
    src="https://picsum.photos/id/1080/600/600"
    alt="Strawberries"
  />
);

Please click on 'Go Live' in the bottom right corner to run the web service on port 8080. Then, you can refresh the Web 8080 Tab to preview the web page.

Summary

Congratulations! You have completed the Lazy-Loading Image lab. You can practice more labs in LabEx to improve your skills.

Other React Tutorials you may like