UNPKG

@tanstack/react-db

Version:

React integration for @tanstack/db

116 lines (115 loc) 4.91 kB
import { useRef, useCallback, useSyncExternalStore } from "react"; import { normalizeLiveQueryWindowPageSize, getLiveQueryWindowInputKind, compareLiveQueryWindowDependencies, resolveLiveQueryWindowInput, createLiveQueryCollection, getLiveQueryWindowCollectionWarning, assertLiveQueryWindowManyResult, shouldPreserveLiveQueryWindowPageCount, createLiveQueryWindowController, fetchNextLiveQueryWindowPage } from "@tanstack/db"; const DEFAULT_GC_TIME_MS = 1; function useLiveInfiniteQuery(queryFnOrCollection, config, deps = []) { const pageSize = normalizeLiveQueryWindowPageSize(config.pageSize); const initialPageParam = config.initialPageParam ?? 0; const inputIsCollection = getLiveQueryWindowInputKind(queryFnOrCollection) === `collection`; const committedRef = useRef(null); const committed = committedRef.current; const inputKind = inputIsCollection ? `collection` : `query`; const dependencyComparison = compareLiveQueryWindowDependencies( committed?.dependencies, deps ); const dependenciesChanged = !inputIsCollection && dependencyComparison.changed; const dependenciesStructurallyEqual = !inputIsCollection && dependencyComparison.structurallyEqual; const needsNewCollection = committed === null || committed.inputKind !== inputKind || inputIsCollection && committed.inputCollection !== queryFnOrCollection || dependenciesChanged; const pageShapeChanged = committed === null || committed.pageSize !== pageSize || committed.initialPageParam !== initialPageParam; const needsNewController = committed === null || needsNewCollection || pageShapeChanged; let renderState = committed; if (needsNewController) { let collection = committed?.collection; let warning = null; if (needsNewCollection) { const input = resolveLiveQueryWindowInput(queryFnOrCollection); if (input.kind === `collection`) { collection = input.collection; } else { collection = createLiveQueryCollection({ query: input.query.limit(pageSize + 1).offset(0), // Construction happens during render. Synchronization starts only when // useSyncExternalStore commits the controller subscription. startSync: false, gcTime: DEFAULT_GC_TIME_MS }); } } if (!collection) { throw new Error(`useLiveInfiniteQuery: Failed to create a collection.`); } if (inputIsCollection) { warning = getLiveQueryWindowCollectionWarning(collection, pageSize + 1) ?? null; } else { assertLiveQueryWindowManyResult(collection); } const canPreservePageCount = shouldPreserveLiveQueryWindowPageCount({ hasPreviousController: committed !== null, previousInputKind: committed?.inputKind, inputKind, sameCollection: inputIsCollection && committed?.inputCollection === collection, dependenciesChanged, dependenciesStructurallyEqual, pageShapeChanged }); const previousPageCount = committed ? Math.max(1, committed.controller.getSnapshot().pages.length) : 1; const initialPageCount = canPreservePageCount ? previousPageCount : 1; renderState = { inputKind, inputCollection: inputIsCollection ? collection : null, dependencies: inputIsCollection ? null : [...deps], pageSize, initialPageParam, collection, controller: createLiveQueryWindowController(collection, { pageSize, initialPageParam, initialPageCount }), warning, warned: false }; } const currentRenderState = renderState; const controller = currentRenderState.controller; const subscribe = useCallback( (onStoreChange) => { const unsubscribe = controller.subscribe(onStoreChange); committedRef.current = currentRenderState; if (currentRenderState.warning && !currentRenderState.warned) { currentRenderState.warned = true; console.warn(currentRenderState.warning); } return unsubscribe; }, [controller, currentRenderState] ); const getSnapshot = useCallback(() => controller.getSnapshot(), [controller]); const snapshot = useSyncExternalStore(subscribe, getSnapshot); const fetchNextPage = useCallback( () => fetchNextLiveQueryWindowPage(controller), [controller] ); return { data: snapshot.data, state: snapshot.state, status: snapshot.status, isLoading: snapshot.isLoading, isReady: snapshot.isReady, isIdle: snapshot.isIdle, isError: snapshot.isError, isCleanedUp: snapshot.isCleanedUp, collection: snapshot.collection, isEnabled: snapshot.isEnabled, pages: snapshot.pages, pageParams: snapshot.pageParams, fetchNextPage, hasNextPage: snapshot.hasNextPage, isFetchingNextPage: snapshot.isFetchingNextPage, error: snapshot.error }; } export { useLiveInfiniteQuery }; //# sourceMappingURL=useLiveInfiniteQuery.js.map