UNPKG

@tanstack/react-db

Version:

React integration for @tanstack/db

149 lines (148 loc) 5.5 kB
import { useRef, useSyncExternalStore } from "react"; import { BaseQueryBuilder, CollectionImpl, createLiveQueryCollection } from "@tanstack/db"; const DEFAULT_GC_TIME_MS = 1; function useLiveQuery(configOrQueryOrCollection, deps = []) { const isCollection = configOrQueryOrCollection && typeof configOrQueryOrCollection === `object` && typeof configOrQueryOrCollection.subscribeChanges === `function` && typeof configOrQueryOrCollection.startSyncImmediate === `function` && typeof configOrQueryOrCollection.id === `string`; const collectionRef = useRef( null ); const depsRef = useRef(null); const configRef = useRef(null); const versionRef = useRef(0); const snapshotRef = useRef(null); const needsNewCollection = !collectionRef.current || isCollection && configRef.current !== configOrQueryOrCollection || !isCollection && (depsRef.current === null || depsRef.current.length !== deps.length || depsRef.current.some((dep, i) => dep !== deps[i])); if (needsNewCollection) { if (isCollection) { configOrQueryOrCollection.startSyncImmediate(); collectionRef.current = configOrQueryOrCollection; configRef.current = configOrQueryOrCollection; } else { if (typeof configOrQueryOrCollection === `function`) { const queryBuilder = new BaseQueryBuilder(); const result = configOrQueryOrCollection(queryBuilder); if (result === void 0 || result === null) { collectionRef.current = null; } else if (result instanceof CollectionImpl) { result.startSyncImmediate(); collectionRef.current = result; } else if (result instanceof BaseQueryBuilder) { collectionRef.current = createLiveQueryCollection({ query: configOrQueryOrCollection, startSync: true, gcTime: DEFAULT_GC_TIME_MS }); } else if (result && typeof result === `object`) { collectionRef.current = createLiveQueryCollection({ startSync: true, gcTime: DEFAULT_GC_TIME_MS, ...result }); } else { throw new Error( `useLiveQuery callback must return a QueryBuilder, LiveQueryCollectionConfig, Collection, undefined, or null. Got: ${typeof result}` ); } depsRef.current = [...deps]; } else { collectionRef.current = createLiveQueryCollection({ startSync: true, gcTime: DEFAULT_GC_TIME_MS, ...configOrQueryOrCollection }); depsRef.current = [...deps]; } } } if (needsNewCollection) { versionRef.current = 0; snapshotRef.current = null; } const subscribeRef = useRef(null); if (!subscribeRef.current || needsNewCollection) { subscribeRef.current = (onStoreChange) => { if (!collectionRef.current) { return () => { }; } const unsubscribe = collectionRef.current.subscribeChanges(() => { versionRef.current += 1; onStoreChange(); }); if (collectionRef.current.status === `ready`) { versionRef.current += 1; onStoreChange(); } return () => { unsubscribe(); }; }; } const getSnapshotRef = useRef(null); if (!getSnapshotRef.current || needsNewCollection) { getSnapshotRef.current = () => { const currentVersion = versionRef.current; const currentCollection = collectionRef.current; if (!snapshotRef.current || snapshotRef.current.version !== currentVersion || snapshotRef.current.collection !== currentCollection) { snapshotRef.current = { collection: currentCollection, version: currentVersion }; } return snapshotRef.current; }; } const snapshot = useSyncExternalStore( subscribeRef.current, getSnapshotRef.current ); const returnedSnapshotRef = useRef(null); const returnedRef = useRef(null); if (!returnedSnapshotRef.current || returnedSnapshotRef.current.version !== snapshot.version || returnedSnapshotRef.current.collection !== snapshot.collection) { if (!snapshot.collection) { returnedRef.current = { state: void 0, data: void 0, collection: void 0, status: `disabled`, isLoading: false, isReady: false, isIdle: false, isError: false, isCleanedUp: false, isEnabled: false }; } else { const entries = Array.from(snapshot.collection.entries()); let stateCache = null; let dataCache = null; returnedRef.current = { get state() { if (!stateCache) { stateCache = new Map(entries); } return stateCache; }, get data() { if (!dataCache) { dataCache = entries.map(([, value]) => value); } return dataCache; }, collection: snapshot.collection, status: snapshot.collection.status, isLoading: snapshot.collection.status === `loading` || snapshot.collection.status === `initialCommit`, isReady: snapshot.collection.status === `ready`, isIdle: snapshot.collection.status === `idle`, isError: snapshot.collection.status === `error`, isCleanedUp: snapshot.collection.status === `cleaned-up`, isEnabled: true }; } returnedSnapshotRef.current = snapshot; } return returnedRef.current; } export { useLiveQuery }; //# sourceMappingURL=useLiveQuery.js.map