Skip to content
Esc
navigateopen⌘Jpreview
On this page

Overview

A React implementation of the Intersection Observer API that tells you when an element enters or leaves the viewport. Use hooks for React state or effects, or <InView> for render props and plain children.

Use it to lazy-load content, trigger scroll-based animations, track impressions, prefetch data, highlight visible sections, and load more results.

Install

npm install react-intersection-observer
pnpm add react-intersection-observer
yarn add react-intersection-observer
bun add react-intersection-observer
import { useInView } from "react-intersection-observer";

export function Section() {
  const { ref, inView } = useInView();

  return <section ref={ref}>{inView ? "In view" : "Waiting"}</section>;
}

Attach ref to an element and use inView in the render. The browser viewport is the root by default, and any intersection flips the state. Set a threshold, margin, or custom root when that default is not enough.

entry is the latest observer result, so read geometry from it. It stays undefined until the browser delivers the first accepted notification.

Choose an API

When you need to Use Why
Change what a component renders useInView Returns a ref, inView, and the latest entry.
Run an impression, prefetch, or analytics callback useOnInView Calls your callback without a hook-owned state update.
Keep observation close to render props or a wrapper <InView> Provides render props and supports plain children.

Try it

The hook above uses the browser viewport. This demo adds a custom scroll root and a threshold, so you can see how options change the same inView state.

See when an element becomes visible
Step 2 · Scroll this panel to reveal the observed card ↓
Feed item 1A small feed item
Feed item 2A small feed item
Feed item 3A small feed item
Feed item 4A small feed item
Feed item 5A small feed item
Feed item 6A small feed item
QueuedWatching
Feature card is waiting

Scroll until enough of this card is visible.

Waiting for visibility
Feed item 7A small feed item
Feed item 8A small feed item
Feed item 9A small feed item

What you get

  • Shared observer instances. Targets that use the same options share one IntersectionObserver, so observing hundreds of elements is cheap.
  • Types in the package. Hooks, components, options, and entries are typed. There is no @types package to install.
  • Two test layers. react-intersection-observer/test-utils drives deterministic transitions, and Browser Mode runs the browser’s own observer.
  • Separate entry points. Import only useInView and the rest is tree shaken away, around 1.15kB gzipped.

Where to go next

Was this page helpful?