Skip to content

Instantly share code, notes, and snippets.

@mrcoles
Last active December 20, 2021 06:05
Show Gist options
  • Save mrcoles/f82827d4ff42f4ec0c5b4d008ddd55eb to your computer and use it in GitHub Desktop.
Save mrcoles/f82827d4ff42f4ec0c5b4d008ddd55eb to your computer and use it in GitHub Desktop.
A simple hook for running an IntersectionObserver inside a React FunctionComponent
import { useEffect, useRef } from 'react';
export type OnIntersect = (elt: HTMLElement) => void;
/**
* Hook for running an IntersectionObserver.
* @param onIntersect this is used in the deps of useEffect, you can
* employ useCallback to prevent it from running
* after every render
* @param args
* @returns an HTMLElement `ref`, make sure to set it to a component
*/
export const useIntersectionObserver = (
onIntersect: OnIntersect,
{
threshold = 0,
root = null,
rootMargin = undefined,
}: IntersectionObserverInit = {}
) => {
const ref = useRef<HTMLElement>();
let observer: IntersectionObserver;
useEffect(() => {
if (window.IntersectionObserver) {
const callback: IntersectionObserverCallback = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
onIntersect(entry.target as HTMLElement);
observer.unobserve(entry.target);
}
});
};
const args = { threshold, root, rootMargin };
observer = new IntersectionObserver(callback, args);
observer.observe(ref.current);
return () => observer.disconnect();
}
}, [onIntersect, JSON.stringify(threshold), root, rootMargin]);
return ref;
};
@mrcoles
Copy link
Author

mrcoles commented Dec 20, 2021

Example:

import React from 'react';

const onObserveSetAnimate = (elt: HTMLElement) => elt.classList.add('animate');

const Foo = () => {
  const ref = useIntersectionObserver(onObserveSetAnimate);
  return <div ref={ref}>hello, world</div>;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment