Custom React Hooks: useIntersectionObserver()

Krzysztof Kałamarski's photo
Krzysztof Kałamarski
·Sep 16, 2021·

2 min read

Custom React Hooks: useIntersectionObserver()

Subscribe to my newsletter and never miss my upcoming articles

Intersection Observer API lets programmers check if a DOM element is currently visible (i.e. intersecting) on the screen.

It can be used to:

  • display floating menu
  • lazy load images
  • perform animations
  • detect if ads are displayed
  • implement infinite scrolling

But now, let's focus on how to use it in React.

If you are like me, a lazy programmer, probably you are not interested in learning the theory. However, if that's not true, you can learn more about how to use this API in the MDN Web Docs.

So, let's see the code - here is copy-paste ready version of the hook:

useIntersectionObserver hook

// useIntersectionObserver.ts

import React, { useEffect, useState } from 'react'

const useIntersectionObserver = (ref: React.RefObject<HTMLElement>) => {
  const [state, setState] = useState<IntersectionObserverEntry>()

  useEffect(() => {
    if (!ref.current) return

    const observer = new IntersectionObserver(([elementState]) => setState(elementState), {
      root: null,
      rootMargin: '0px',
      threshold: 0
    })

    observer.observe(ref.current)

    return () => observer.disconnect()
  }, [ref])

  return state
}

export default useIntersectionObserver

It's not that complicated! Let's see how to use it.

// Component.tsx

import React, { useRef } from "react";
import useIntersectionObserver from "./useIntersectionObserver";

const Component = () => {
  const ref = useRef<HTMLDivElement>(null);
  const intersection = useIntersectionObserver(ref);

  return (
    <section style={{ position: "relative" }}>
      <div style={{ position: "fixed" }}>
        {intersection?.isIntersecting
          ? "Element is visible"
          : "Element is not visible - scroll down"}
      </div>
      <div style={{ height: "800px" }} />
      <div ref={ref} style={{ height: "200px", background: "red" }} />
    </section>
  );
};

export default Component;

You can edit the working example on CodeSandbox: Edit useIntersectionObserver-example

I hope you find it useful. Stay tuned for more copy-paste ready custom react hook posts!

 
Share this