(props: LoadMoreProps, ref: RefObject<HTMLElement | null>)
| 35 | } |
| 36 | |
| 37 | export function useLoadMore(props: LoadMoreProps, ref: RefObject<HTMLElement | null>): void { |
| 38 | let {isLoading, onLoadMore, scrollOffset = 1, items} = props; |
| 39 | |
| 40 | // Handle scrolling, and call onLoadMore when nearing the bottom. |
| 41 | let isLoadingRef = useRef(isLoading); |
| 42 | let prevProps = useRef(props); |
| 43 | let onScroll = useCallback(() => { |
| 44 | if (ref.current && !isLoadingRef.current && onLoadMore) { |
| 45 | let shouldLoadMore = |
| 46 | ref.current.scrollHeight - ref.current.scrollTop - ref.current.clientHeight < |
| 47 | ref.current.clientHeight * scrollOffset; |
| 48 | |
| 49 | if (shouldLoadMore) { |
| 50 | isLoadingRef.current = true; |
| 51 | onLoadMore(); |
| 52 | } |
| 53 | } |
| 54 | }, [onLoadMore, ref, scrollOffset]); |
| 55 | |
| 56 | let lastItems = useRef(items); |
| 57 | useLayoutEffect(() => { |
| 58 | // Only update isLoadingRef if props object actually changed, |
| 59 | // not if a local state change occurred. |
| 60 | if (props !== prevProps.current) { |
| 61 | isLoadingRef.current = isLoading; |
| 62 | prevProps.current = props; |
| 63 | } |
| 64 | |
| 65 | // TODO: Eventually this hook will move back into RAC during which we will accept the collection as a option to this hook. |
| 66 | // We will only load more if the collection has changed after the last load to prevent multiple onLoadMore from being called |
| 67 | // while the data from the last onLoadMore is being processed by RAC collection. |
| 68 | let shouldLoadMore = |
| 69 | ref?.current && |
| 70 | !isLoadingRef.current && |
| 71 | onLoadMore && |
| 72 | (!items || items !== lastItems.current) && |
| 73 | ref.current.clientHeight === ref.current.scrollHeight; |
| 74 | |
| 75 | if (shouldLoadMore) { |
| 76 | isLoadingRef.current = true; |
| 77 | onLoadMore?.(); |
| 78 | } |
| 79 | |
| 80 | lastItems.current = items; |
| 81 | }, [isLoading, onLoadMore, props, ref, items]); |
| 82 | |
| 83 | // TODO: maybe this should still just return scroll props? |
| 84 | // Test against case where the ref isn't defined when this is called |
| 85 | // Think this was a problem when trying to attach to the scrollable body of the table in OnLoadMoreTableBodyScroll |
| 86 | useEvent(ref, 'scroll', onScroll); |
| 87 | } |
no test coverage detected