import { RefObject, useEffect, useRef, useState } from 'react'; import { CollectionReachBottom } from '../state/CollectionReachBottom'; import { ScrollableWindow } from '../reach-bottom-listener'; import { CollectionState, FiltersMap } from '@wix/bex-core'; import { useWixPatternsContainer } from '@wix/bex-core/react'; import { addEventListener } from '@wix/bex-core/util'; export interface UseCollectionReachBottomParams< T, F extends FiltersMap = FiltersMap, > { collection: CollectionState; containerRef?: RefObject; scrollMoreAlways?: boolean; } export function useCollectionReachBottom({ collection, containerRef, scrollMoreAlways, }: UseCollectionReachBottomParams) { const targetRef = useRef(null); const { lodash } = useWixPatternsContainer(); const { result: { keyedItems }, } = collection; const [collectionReachBottom] = useState( () => new CollectionReachBottom({ collection, lodash, }), ); useEffect(() => { if (containerRef?.current == null) { return; } collectionReachBottom.reachBottom.container = containerRef?.current; collectionReachBottom.reachBottom.target = targetRef?.current; const disposers = [ addEventListener(collection.emitter, 'triggerReachBottomListener', () => { collectionReachBottom.triggerListenerIfReached(); }), ]; collectionReachBottom.subscribe(); return () => { collectionReachBottom.reachBottom.target = null; disposers.forEach((d) => d()); collectionReachBottom.unsubscribe(); }; }, []); // Check if should load more items (scrollable container is not filled yet) after new data has been rendered useEffect(() => { // In jsdom element dimensions are always 0, so calculations inside `CollectionReachBottom` are not relevant. if (process.env.NODE_ENV === 'test') { return; } if (scrollMoreAlways || containerRef?.current?.scrollHeight) { collectionReachBottom.triggerListenerIfReached(); } }, [keyedItems.length]); return { containerRef, targetRef }; }