React hook to use IntersectionObserver declaratively.
npm install react-intersection-observer-hook
This is an easy to use React hook package for using Insersection Observer declaratively. By using this hook, you can easily track if a component is visible or not, create lazy loading images, trigger animations on entering or leaving the viewport, implement infinite scroll etc.
Live demo is here.
This package relies on Intersection Observer API. Browser compatibility can be seen in here.
If you want to support the browsers those are not supporting it natively, you can use a polyfill.
For React v19, it is recommended to use versions after v4, since it uses cleanup functions for refs.
For older versions of React, you can stick with v3 until you migrate to React 19.
``sh`
npm install react-intersection-observer-hook
`jsx
import React, { useEffect } from 'react';
import { useIntersectionObserver } from 'react-intersection-observer-hook';
// ...
function Example() {
// useIntersectionObserver returns a tuple.ref
// We need to give this callback to the node we want to observe.entry
// The second item, is the response of the IntersectionObserver instance.
const [ref, { entry }] = useIntersectionObserver();
const isVisible = entry && entry.isIntersecting;
return (
Component is {isVisible ? 'visible' : 'not visible'}.
If you have a scrollable container, you can set a
root like this:`jsx
import React, { useEffect } from 'react';
import { useIntersectionObserver } from 'react-intersection-observer-hook';
// ...function Example() {
const [ref, { entry, rootRef }] = useIntersectionObserver();
const isVisible = entry && entry.isIntersecting;
return (
Component is {isVisible ? 'visible' : 'not visible'}.
// We use rootRef callback to set the root node.
ref={rootRef}
>
);
}
`If you just want to track visibility, you can also use
useTrackVisibility hook. It mostly has the same API as useIntersectionObserver hook.`jsx
import React, { useEffect } from 'react';
import { useTrackVisibility } from 'react-intersection-observer-hook';
// ...function Example() {
//
useTrackVisibility also returns a tuple like useIntersectionObserver.
// First item is the same ref callback to set the node to observe.
// Second item is an object that we can use to decide if a node is visible.
// entry: Same object which is returned by useIntersectionObserver.
// rootRef: Same ref callback which is returned by useIntersectionObserver.
// isVisible: Becomes true/false based on the response of IntersectionObserver.
const [ref, { entry, rootRef, isVisible }] = useTrackVisibility({
// In addition to the IntersectionObserver arguments, you can use once flag
// to watch the visibility of an element once, so isVisible stays true after the element is visible for the first time.
// once: true,
}); return (
Component is {isVisible ? 'visible' : 'not visible'}.
);
}
`> [!NOTE]
> The returned
ref from useIntersectionObserver and useTrackVisibility can be attached to only one element at a time. If you assign it to multiple elements, only the most recently assigned element will be observed.
> Currently, there is no support for observing multiple elements by using the same ref. Documentation will be updated when this is implemented.You can find more usage examples in the
demo app in this repository.Arguments
$3
-
rootMargin: Indicates the margin value around the root element. Default value is 0 for all directions (top, right, bottom and left).
- threshold: Threshold value (or values) to trigger the observer._For more info, you can check here and here._
$3
Gets the same arguments as
useIntersectionObserver. In addition:-
once: When set true, isVibisle stays as true after the element is visible for the first time. Default false`.Thanks goes to these wonderful people (emoji key):
KimSeonghyeon 💻 | ||||||
Add your contributions | ||||||
This project follows the all-contributors specification. Contributions of any kind welcome!