import React from "react"; type Param = { elementRef?: React.RefObject; className?: string; elId?: string; options?: IntersectionObserverInit; removeIntersected?: boolean; delay?: number; }; let timeout: any; export default function useIntersectionObserver({ elementRef, className, options, removeIntersected, delay, elId, }: Param) { const [isIntersecting, setIsIntersecting] = React.useState(false); const [refresh, setRefresh] = React.useState(0); const observerTriggerDelay = delay || 200; const observerCallback: IntersectionObserverCallback = React.useCallback( (entries, observer) => { const entry = entries[0]; window.clearTimeout(timeout); if (entry.isIntersecting) { timeout = setTimeout(() => { setIsIntersecting(true); if (removeIntersected) { observer.unobserve(entry.target); } }, observerTriggerDelay); } else { setIsIntersecting(false); } }, [] ); React.useEffect(() => { const element = elId ? document.getElementById(elId) : elementRef?.current; const elements = className ? document.querySelectorAll(`.${className}`) : null; if (!element && !className && refresh < 5) { requestAnimationFrame(() => { setTimeout(() => { setRefresh(refresh + 1); }, 2000); }); return; } const observer = new IntersectionObserver(observerCallback, { rootMargin: "0px 0px 0px 0px", ...options, }); if (elements) { elements.forEach((el) => { observer.observe(el); }); } else if (element) { observer.observe(element); } }, [refresh]); return { isIntersecting }; }