React Intersection Observer Hook

4.0.2 · active · verified Tue Apr 21

The `react-intersection-observer-hook` package provides declarative React hooks, specifically `useIntersectionObserver` and `useTrackVisibility`, to interact with the browser's native Intersection Observer API. It simplifies detecting when a React component enters or exits the viewport, enabling features like lazy loading, infinite scrolling, and triggering animations. The current stable version is 4.0.2, with active development focusing on modern React compatibility, demonstrated by its recent update for React 19 in v4.0.0. Releases are frequent, addressing bugs and improving API ergonomics. Key differentiators include a dedicated `useTrackVisibility` for simpler boolean visibility checks, explicit `rootRef` handling for scrollable containers, and robust support for both ES Modules and CommonJS environments since v3.0.0, ensured through modern bundling practices.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates how to use `useTrackVisibility` to detect when a component enters or leaves the viewport, changing its background color. It also shows how to specify a custom scrollable container using `rootRef`.

import React from 'react';
import { useTrackVisibility } from 'react-intersection-observer-hook';

function MyTrackedComponent() {
  const [ref, { isVisible, entry, rootRef }] = useTrackVisibility({
    // Optionally, track visibility only once
    // once: true,
    // Customize intersection threshold (0.0 to 1.0)
    threshold: 0.5,
    // Add margin around the root (e.g., '10px 20px 30px 40px')
    // rootMargin: '0px 0px -50px 0px',
  });

  // For a scrollable container (e.g., div with overflow-y: scroll),
  // attach rootRef to the container. Otherwise, it defaults to the viewport.
  const ScrollableContainer = React.forwardRef((props, forwardedRef) => (
    <div ref={forwardedRef} style={{ height: '300px', overflowY: 'scroll', border: '1px solid gray' }}>
      {props.children}
    </div>
  ));

  return (
    <div style={{ height: '1000px', padding: '200px 0' }}>
      <p>Scroll down to see the tracked element.</p>
      <ScrollableContainer ref={rootRef}>
        <div style={{ height: '400px', background: 'lightblue', margin: '100px 0' }}></div>
        <div ref={ref} style={{ height: '200px', background: isVisible ? 'lightgreen' : 'lightcoral', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <h2>Element is {isVisible ? 'visible!' : 'not visible.'}</h2>
          {entry && <p>Intersection Ratio: {entry.intersectionRatio.toFixed(2)}</p>}
        </div>
        <div style={{ height: '400px', background: 'lightblue', margin: '100px 0' }}></div>
      </ScrollableContainer>
    </div>
  );
}

export default MyTrackedComponent;

view raw JSON →