useIntersection

Exports Size
loading...
Gzip Size
loading...
Brotli Size
Source Code
View on GitHub
Docs
Edit this page

Tracks the changes in the intersection of a target element with an ancestor element or with a top-level document's viewport. Uses the Intersection Observer API (opens in a new tab).

Usage

Here is an example of a <Thumbnail /> component that uses the useIntersection to lazy load the image.

import { useState, useCallback } from 'react';
import { useIntersection } from 'foxact/use-intersection';
 
// A foxact hook that can be used to reset the state when the props changes
// see: https://foxact.skk.moe/use-component-will-receive-update
import { useComponentWillReceiveUpdate } from 'foxact/use-component-will-receive-update';
 
interface ThumbnailProps {
  src: string;
  isLazy?: boolean;
}
 
const Thumbnail = ({ src, isLazy }: ThumbnailProps) => {
  const [setIntersection, isIntersected, resetIsIntersected] = useIntersection<HTMLImageElement>({
    rootRef: null, // optional, the ref of the ancestor element
    rootMargin: '200px', // optional
    disabled: !isLazy // optional, allows to create reusable thumbnail component that supports both lazy and eager loading
  });
 
  // Reset the `isIntersected` state when the `src` prop changes
  // You can find the docs about `useComponentWillReceiveUpdate` here: https://foxact.skk.moe/use-component-will-receive-update
  useComponentWillReceiveUpdate(resetIsIntersected, [src])
 
  return (
    <img
      // Use callback ref to tell the `useIntersection` hook which image element needs to be observed
      // Wraps the callback ref with `useCallback` to avoid unnecessary invocations during re-render.
      // See also react documentation about callback ref: https://react.dev/reference/react-dom/components/common#ref-callback
      ref={useCallback((el: HTMLImageElement | null) => {
        if (isLazy) {
          setIntersection(el);
        }
      }, [isLazy, setIntersection])}
      decoding="async"
      alt={alt}
      // https://stackoverflow.com/questions/6018611/smallest-data-uri-image-possible-for-a-transparent-image
      src={isIntersected ? src : 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'}
    />
  );
}