Scrolling up · bottom of page in view: no

All hooks / Elements

useInView

252 B minified and brotliedSourceMarkdown✓ Works in all modern browsers

Whether an element is visible in the viewport, using IntersectionObserver.

Returns a callback ref to put on the element. It is false on the server, during hydration, and until the observer first reports. Does not re-render on scroll, only when visibility changes.

Import

import { useInView } from '@vincent.ri/react-tils'
// or only this hook
import { useInView } from '@vincent.ri/react-tils/useInView'

Usage

// Load more when the sentinel gets within 300px of the viewport.
const [ref, inView] = useInView<HTMLDivElement>({ rootMargin: '300px' })
useEffect(() => {
  if (inView) loadMore()
}, [inView])
return <div ref={ref} />

Live demo

Watches the footer at the very bottom of the page.

footer in view: no

When to use it

Lazy-loading content or images, loading the next page of an infinite list, starting an animation or video when it scrolls into view, or tracking impressions.

When not to

You need the exact scroll position; use useWindowScroll. For images alone, <img loading="lazy"> needs no JS.

API

function useInView<T extends Element = HTMLElement>(options?: InViewOptions): [(element: T | null) => void, boolean]
ParameterDescription
optionsrootMargin, threshold, and once. All optional.

Returns [ref, inView]. Pass ref to the element's ref prop.

Types

export type InViewOptions = {
  /** Grow or shrink the viewport for the check, like CSS margin. E.g. `'200px'` triggers 200px early. */
  rootMargin?: string;
  /** Fraction of the element (0 to 1) that must be visible. Default `0`: any pixel. */
  threshold?: number;
  /** Stop observing after the first time the element is in view. Default `false`. */
  once?: boolean;
};

Browser support

UsesChromeEdgeFirefoxSafariChrome AndroidSafari iOS
IntersectionObserverWidely available51+15+55+12.1+51+12.2+

First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).

Coming from another library?

Other libraries call this useIntersection, useIntersectionObserver, useInViewport.