---
title: Overview
seo:
  description: React hooks and components that tell you when an element enters or leaves the viewport or a scroll container.
sidebar:
  label: Overview
  order: 0
---

<p class="text-lg text-muted-foreground">
  A React implementation of the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">Intersection Observer API</a> that tells you when an element enters or leaves the viewport. Use <a href="/api/core-apis#useinview">hooks</a> for React state or effects, or <a href="/api/core-apis#inview">&lt;InView&gt;</a> for render props and plain children.
</p>

Use it to [lazy-load content](/guides/recipes#lazy-image-loading), trigger [scroll-based animations](/guides/recipes#scroll-triggered-animation), [track impressions](/guides/recipes#track-an-impression), prefetch data, highlight visible sections, and [load more results](/guides/recipes#infinite-scrolling).

## Install

```package-install
react-intersection-observer
```

```tsx
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`](/api/core-apis#useinview) | Returns a `ref`, `inView`, and the latest `entry`. |
| Run an impression, prefetch, or analytics callback | [`useOnInView`](/api/core-apis#useoninview) | Calls your callback without a hook-owned state update. |
| Keep observation close to render props or a wrapper | [`<InView>`](/api/core-apis#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.

<ObserverDemo />

## 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](/testing/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

- [Core APIs](/api/core-apis) covers the full contracts and return values.
- [Observer options](/api/configuration) covers thresholds, margins, and scroll containers.
- [Recipes](/guides/recipes) builds lazy loading, reveals, impressions, and infinite lists.
- [Testing](/testing) covers verification, and [SSR and fallbacks](/guides/ssr) covers server rendering.
