This hook is an updated version from my previous Post
interface IntersectionHookInit extends IntersectionObserverInit {
// In case I want to add something
}
type OnIntersection = (isIntersecting: boolean, ob: IntersectionObserver) => boolean | void;
const DefaultOptions: IntersectionHookInit = {
root: null,
threshold: 0,
}
// Most of time we only need ob until intersecting, so return false here to disconnect ob.
const DefaultOnIntersection: OnIntersection = (isIntersecting, ob) => {
if (isIntersecting) return false;
}
export function useIntersection(onIntersection: OnIntersection = DefaultOnIntersection, options: IntersectionHookInit = DefaultOptions) {
const [isIntersecting, setIsIntersecting] = useState(false);
const elemRef = useRef<null | Element| undefined>(null);
const setElem = (elem:any) => {
elemRef.current = elem;
}
useEffect(() => {
if (!elemRef.current) return;
let isUnmounted = false;
const ob = new IntersectionObserver(([entry]) => {
if (isUnmounted) return;
const isElementIntersecting = entry.isIntersecting;
if (onIntersection(isElementIntersecting, ob) === false) {
ob.disconnect();
};
setIsIntersecting(isElementIntersecting)
}, { ...options })
ob.observe(elemRef.current);
return () => {
ob.disconnect();
isUnmounted = true;
}
}, [elemRef.current, options]);
return [isIntersecting, setElem] as const;
}
Usage:
export function LazyLoad(props) {
const [isIntersecting, ref] = useIntersection();
return (
<div ref={ref}>
{isIntersecting ? props.children : null}
</div>
)
}
Thanks for reading!
Top comments (0)