Implementing Lazy Loading of Images with Intersection Observer in React

Implementing Lazy Loading of Images with Intersection Observer in React

Lazy loading images is a technique that delays the loading of images until they are needed — when they’re about to enter the user’s viewport. This is especially useful for improving page performance and reducing unnecessary data usage, particularly on image-heavy web pages. In this article, we’ll walk through how to build a lazy-loading image feature using the Intersection Observer API in React.

We’ll start by setting up a simple Lazyload component that displays a placeholder initially. When the image element scrolls into view, we’ll load the actual image.

Step 1: Setting Up the Component

Let’s begin with a component called Lazyload, which will take in src and alt props. These props represent the URL of the image and the alt text for accessibility, respectively.


import { useEffect, useRef, useState } from 'react';

export default function Lazyload({ src, alt }) {
  const [visible, setVisible] = useState(false);
  const imageRef = useRef(null);

  useEffect(() => {
    // Set up the IntersectionObserver
    const observer = new IntersectionObserver((entries, obs) => {
      for (const entry of entries) {
        if (entry.isIntersecting) {
          setVisible(true); // Trigger the image to load
          obs.disconnect(); // Disconnect once the image is loaded
        }
      }
    });

    if (imageRef.current) {
      observer.observe(imageRef.current);
    }

    // Cleanup function to disconnect the observer
    return () => {
      observer.disconnect();
    };
  }, []);

  return (
    <div
      ref={imageRef}
      style={{
        height: '500px',
        width: '500px',
        backgroundColor: 'lightgray',
        backgroundImage: visible
          ? `url(${src})`
          : `url('https://craftsnippets.com/articles_images/placeholder/placeholder.jpg')`,
        backgroundRepeat: 'no-repeat',
        backgroundSize: 'cover',
        margin: '50px',
      }}
    >
      {visible && <img src={src} alt={alt} width="500px" height="500px" />}
    </div>
  );
}        

Code Breakdown

  • State and Ref Setup: We initialize visible state to determine if the image should load. imageRef is used to refer to the image container element.
  • Intersection Observer Setup: Inside the useEffect, we create an IntersectionObserver instance. It checks if the element referred to by imageRef is in the viewport. If entry.isIntersecting is true, it means the image is in view, so we set visible to true and disconnect the observer to prevent further unnecessary checks.
  • Placeholder and Loaded Image: Initially, the div displays a placeholder image by setting backgroundImage. When visible is true, the img element with the actual src is rendered on top of the placeholder image, effectively lazy loading the image when it becomes visible.

Step 2: Fetching and Displaying Images in the Main Component

In the main App component, we’ll use the Lazyload component to display a list of images. We fetch images from the Picsum API and store them in the images state.


import { useEffect, useState } from 'react';
import Lazyload from './Lazyload';
import './App.css';

function App() {
  const [images, setImages] = useState([]);

  useEffect(() => {
    fetch('https://picsum.photos/v2/list?limit=50')
      .then(response => response.json())
      .then(data => setImages(data))
      .catch(err => console.log('Cannot fetch images', err));
  }, []);

  return (
    <div>
      <h1>Lazy Loading Images</h1>
      {images.length > 0 && (
        <>
          {images.map((img, i) => (
            <Lazyload key={i} src={img.download_url} alt={img.author} />
          ))}
        </>
      )}
    </div>
  );
}

export default App;        

Code Breakdown

  • Fetching Images: We use useEffect to fetch images from the Picsum API when the component mounts. The fetched images are stored in the images state.
  • Using Lazyload Component: After fetching, we map over images and render each one using the Lazyload component, passing in the image URL (img.download_url) and the author name as alt.

Why Use Intersection Observer for Lazy Loading?

The Intersection Observer API is an efficient way to handle lazy loading compared to older techniques. It allows us to observe when an element enters the viewport, without having to listen for scroll events continuously, which can be costly for performance.


Key Advantages

  1. Improved Page Load Speed: By only loading images as they’re needed, we reduce the initial page load time.
  2. Efficient Performance: Intersection Observer is optimized for performance, using fewer resources than continuously checking the element’s position.
  3. Reduced Data Usage: Lazy loading helps save data by only loading images that the user actually views.


Summary

With the Lazyload component and the IntersectionObserver API, we’ve built an efficient and straightforward way to lazy-load images in React. The component shows a placeholder image initially and loads the actual image only when it scrolls into the viewport. This technique not only improves performance but also enhances the user experience, particularly on pages with a large number of images.

Lazy loading can be an essential tool in modern web development, as it contributes to faster load times, better performance, and reduced data usage, making it an excellent addition to any performance-focused project.


要查看或添加评论,请登录

Vivek Neupane的更多文章

社区洞察

其他会员也浏览了