/
githubmirror
/
ydb-embedded-ui
Обзор
Документация
Войти
/
githubmirror
/
ydb-embedded-ui
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/containers/Operations/useOperationsInfiniteQuery.ts
124 строки
4 KB
Hellen
feat: improve table compaction (#3967)
05 июн 2026, 15:28
Не верифицирован
05 июн 2026, 15:28
4665f40
Код
Авторство
О чём код?
import React from 'react'; import {throttle} from 'lodash'; import {DEFAULT_PAGE_SIZE, operationsApi} from '../../store/reducers/operations'; import type {OperationKind} from '../../types/api/operations'; interface UseOperationsInfiniteQueryProps { database: string; kind: OperationKind; pageSize?: number; searchValue: string; scrollContainerRef?: React.RefObject<HTMLElement>; } const DEFAULT_SCROLL_MARGIN = 100; export function useOperationsInfiniteQuery({ database, kind, pageSize = DEFAULT_PAGE_SIZE, searchValue, scrollContainerRef, }: UseOperationsInfiniteQueryProps) { const {data, error, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage} = operationsApi.useGetOperationListInfiniteQuery({ database, kind, page_size: pageSize, }); // Flatten all pages into a single array of operations const allOperations = React.useMemo(() => { if (!data?.pages) { return []; } // Each page is a TOperationList, so we need to extract operations from each return data.pages.flatMap((page) => page.operations || []); }, [data]); const filteredOperations = React.useMemo(() => { const preparedSearchValue = searchValue.trim().toLowerCase(); if (!preparedSearchValue) { return allOperations; } return allOperations.filter((op) => op.id?.toLowerCase().includes(preparedSearchValue)); }, [allOperations, searchValue]); // Auto-load more pages to fill viewport const checkAndLoadMorePages = React.useCallback(async () => { const scrollContainer = scrollContainerRef?.current; if (!scrollContainer || !hasNextPage || isFetchingNextPage) { return; } const {scrollHeight, clientHeight} = scrollContainer; if (scrollHeight <= clientHeight) { await fetchNextPage(); } }, [scrollContainerRef, hasNextPage, isFetchingNextPage, fetchNextPage]); // Check after data updates React.useLayoutEffect(() => { if (!isFetchingNextPage) { // RAF to ensure browser has completed layout and paint const raf = requestAnimationFrame(() => { checkAndLoadMorePages(); }); return () => cancelAnimationFrame(raf); } return undefined; }, [data, isFetchingNextPage, checkAndLoadMorePages]); // Scroll handler for infinite scrolling const handleScroll = React.useCallback(() => { const scrollContainer = scrollContainerRef?.current; if (!scrollContainer) { return; } const {scrollTop, scrollHeight, clientHeight} = scrollContainer; if ( scrollHeight - scrollTop - clientHeight < DEFAULT_SCROLL_MARGIN && hasNextPage && !isFetchingNextPage ) { fetchNextPage(); } }, [scrollContainerRef, hasNextPage, isFetchingNextPage, fetchNextPage]); React.useEffect(() => { const scrollContainer = scrollContainerRef?.current; if (!scrollContainer) { return undefined; } scrollContainer.addEventListener('scroll', handleScroll); return () => scrollContainer.removeEventListener('scroll', handleScroll); }, [scrollContainerRef, handleScroll]); // Resize handler to check if more content is needed when viewport changes React.useEffect(() => { const throttledHandleResize = throttle(checkAndLoadMorePages, 200, { trailing: true, leading: true, }); window.addEventListener('resize', throttledHandleResize); return () => { throttledHandleResize.cancel(); window.removeEventListener('resize', throttledHandleResize); }; }, [checkAndLoadMorePages]); return { operations: filteredOperations, isLoading, isLoadingMore: isFetchingNextPage, error, }; }