import { useEffect, useMemo } from 'react'; import { throttle } from 'throttle-debounce'; import { useWindowSize } from './useWindowSize'; interface Options { active?: boolean; threshold?: number; } export const useScrollEnd = ( item: Element | Element[] | undefined | null, callback?: () => void, { active = true, threshold = 1.5 }: Options = {}, ) => { const debouncedCallback = useMemo( () => callback && throttle(1000, callback), [callback], ); const { innerHeight } = useWindowSize(); useEffect(() => { if (!item || !active || !debouncedCallback) return; const items = Array.isArray(item) ? item : [item]; const positions = items.map((it) => { const { top, height } = it.getBoundingClientRect(); return top + window.scrollY + height; }); const eventHandler = () => { if ( !positions.some( (it) => it < window.scrollY + window.innerHeight * threshold, ) ) return; debouncedCallback(); }; window.addEventListener('scroll', eventHandler); return () => window.removeEventListener('scroll', eventHandler); }, [item, active, innerHeight, debouncedCallback, threshold]); };