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-observerpnpm add react-intersection-observeryarn add react-intersection-observerbun add react-intersection-observerimport { 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.
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
@typespackage to install. - Two test layers.
react-intersection-observer/test-utilsdrives deterministic transitions, and Browser Mode runs the browser’s own observer. - Separate entry points. Import only
useInViewand the rest is tree shaken away, around 1.15kB gzipped.
Where to go next
- Core APIs covers the full contracts and return values.
- Observer options covers thresholds, margins, and scroll containers.
- Recipes builds lazy loading, reveals, impressions, and infinite lists.
- Testing covers verification, and SSR and fallbacks covers server rendering.