DEV Community

Cover image for Utilizing Intersection Observer in React
IHesamI
IHesamI

Posted on

Utilizing Intersection Observer in React

Today, I want to talk about the IntersectionObserver, a built-in JavaScript API which is primarily used for lazy-loading images and implementing infinite scrolling. Creating an instance of this API is straightforward, as demonstrated below:

const observer = new IntersectionObserver(callback,options);
Enter fullscreen mode Exit fullscreen mode

A callback function is required to trigger when intersecting entities change, while options is an object that defines the observer's behavior and policy. Utilizing this API enables the lazy loading of images in a React app. Refer to this page for a comprehensive understanding of this API.

To utilize this API in a React application, you need to follow a few steps.
Firstly Create a file called Observer.js which contains the observer object and its corresponding callback function. The structure of Observer.js will appear as follows:

export let observer;

export function initObserver() {
  observer = new IntersectionObserver(observerCallback);
}


function observerCallback(entries) {
  // TODO
}
Enter fullscreen mode Exit fullscreen mode

The initObserver function initializes the observer object, the body of the observerCallback function will be completed later. The initObserver needs to be called at the top level of the react tree, such as in main.jsx.

To render the images and enable observation, we need to create an Image component, which enables us to use the observer. The code snippet provided below demonstrates the implementation of the Image component.

import React, { useEffect, useRef, useState } from "react";
import { observer } from "./Observer";

export default function Image({ src }) {
  const [isSeen, setIsSeen] = useState(false);
  const containerRef = useRef(null);


  useEffect(() => {
    if (containerRef.current) {
      containerRef.current.onObserve = () => {
        setIsSeen(true);
      };
      observer.observe(containerRef.current);
    }
    return () => observer.unobserve(containerRef.current);
  }, []);


  return isSeen ? (
    <img src={src} />
  ) : (
    <div
      ref={containerRef}
      style={{ width: "250px", height: "350px", backgroundColor: "black" }}
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

This component uses a prop named src, which represents the URL source of the image. Additionally, it requires a ref to reference an alternative element for the image which is called containerRef. In the example given, a basic div with a black background is used, but you have the flexibility to customize this element according to your specific requirements.

In the useEffect setup function, we first check if the containerRef has a reference. If it has, we add a function called onObserve to it. Inside this function, we change the component state isSeen to true, indicating that the image should be rendered and displayed. Then, we make the observer intersects the containerRef. Finally, in the clean-up function of the useEffect, we remove the containerRef from the list of observed entries by calling the unobserve function.

Now, moving on to the final step, we will go back to the Observer.js file and proceed with initializing the body of the observerCallback function. It should verify if an entry intersects and then invoke its onObserve function. Therefore, the updated code will appear as follows:

function observerCallback(entries) {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        entry.target.onObserve();
      }
    });
  }
Enter fullscreen mode Exit fullscreen mode

Thank you for taking the time to read this article. I hope you found it helpful. If you have any questions or comments, please share them with me.

Top comments (0)