snippet

useObserver

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

const useObserver = (options = { threshold: 1 }) => {
  const [isIntersecting, setIsIntersecting] = useState(false);
  const nodeRef = useRef(null);

  useEffect(() => {
    const node = nodeRef.current;
    const observer = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          setIsIntersecting(true);
        } else {
          setIsIntersecting(false);
        }
      });
    }, options);
    observer.observe(node);

    return () => {
      observer.unobserve(node);
    };
  }, [options, isIntersecting]);

  return [isIntersecting, nodeRef];
};

The hook situation

Imagine we wanted to know whether a DOM element is in view? The useObserver hook is a custom hook that notifies us when an element has scrolled into view using the Intersection Observer API.

How to use useObserver

import useObserver from "./useObserver";

const ExampleComponent = () => {
  const [isIntersecting, nodeRef] = useObserver({ threshold: 0.5 });

  return (
    <div style={{ height: "200vh", padding: "10px" }}>
      <div style={{ height: "150vh" }}>Scroll down to see the box</div>
      <div
        ref={nodeRef}
        style={{
          height: "100px",
          backgroundColor: isIntersecting ? "green" : "red",
          transition: "background-color 0.5s ease",
        }}
      >
        {isIntersecting ? "In View" : "Out of View"}
      </div>
    </div>
  );
};

export default ExampleComponent;

In the above example, the useObserver hook is imported and used inside the ExampleComponent. We attach the nodeRef to a div element so that we can monitor the visibility of that element. This particular div will change its background colour to green when it's in view and to red when it's out of view. Additionally, it displays text indicating its visibility status*.

Last updated May 29th, 2024