From d9adec64fc2178468e09218ef70bc90b0332827f Mon Sep 17 00:00:00 2001 From: Aleksandar Date: Thu, 2 Jul 2026 14:58:00 +0200 Subject: [PATCH] core: VirtualTable - changed how scroll to the end is handled for data fetching --- .../components/VirtualTable/VirtualTable.tsx | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/firecms_core/src/components/VirtualTable/VirtualTable.tsx b/packages/firecms_core/src/components/VirtualTable/VirtualTable.tsx index e6e514bf2..7af348d9a 100644 --- a/packages/firecms_core/src/components/VirtualTable/VirtualTable.tsx +++ b/packages/firecms_core/src/components/VirtualTable/VirtualTable.tsx @@ -135,7 +135,7 @@ export const VirtualTable = React.memo>( const [columns, setColumns] = useState(columnsProp); const tableRef = useRef(null); - const endReachCallbackThreshold = useRef(0); + const lastEndReachedDataLength = useRef(undefined); const debouncedScroll = useDebounceCallback(onScrollProp, 200); @@ -242,7 +242,7 @@ export const VirtualTable = React.memo>( }, [filterInput]); const scrollToTop = useCallback(() => { - endReachCallbackThreshold.current = 0; + lastEndReachedDataLength.current = undefined; if (tableRef.current) { tableRef.current.scrollTo(tableRef.current?.scrollLeft, 0); } @@ -278,13 +278,24 @@ export const VirtualTable = React.memo>( const maxScroll = Math.max((data?.length ?? 0) * rowHeight - bounds.height, 0); - const onEndReachedInternal = useCallback((scrollOffset: number) => { - if (onEndReached && (data?.length ?? 0) > 0 && scrollOffset > endReachCallbackThreshold.current + endOffset) { - endReachCallbackThreshold.current = scrollOffset; + const onEndReachedInternal = useCallback(() => { + const dataLength = data?.length ?? 0; + + if (onEndReached && dataLength > 0 && lastEndReachedDataLength.current !== dataLength) { + lastEndReachedDataLength.current = dataLength; onEndReached(); } }, [data?.length, onEndReached]); + useEffect(() => { + if (!onEndReached || loading || !data?.length || !bounds.height || !tableRef.current) { + return; + } + if (tableRef.current.scrollHeight <= tableRef.current.clientHeight) { + onEndReachedInternal(); + } + }, [bounds.height, data?.length, loading, onEndReached, onEndReachedInternal]); + const onScroll = useCallback(({ scrollDirection, scrollOffset, @@ -302,12 +313,12 @@ export const VirtualTable = React.memo>( }) } if (!scrollUpdateWasRequested && (scrollOffset >= maxScroll - endOffset)) - onEndReachedInternal(scrollOffset); - }, [maxScroll, onEndReachedInternal]); + onEndReachedInternal(); + }, [endOffset, maxScroll, onEndReachedInternal]); const onFilterUpdateInternal = useCallback((column: VirtualTableColumn, filterForProperty?: [VirtualTableWhereFilterOp, any]) => { - endReachCallbackThreshold.current = 0; + lastEndReachedDataLength.current = undefined; const filter = filterRef.current; let newFilterValue: VirtualTableFilterValues = filter ? { ...filter } : {};