UNPKG

@tanstack/react-db

Version:

React integration for @tanstack/db

119 lines (118 loc) • 5.23 kB
"use client"; import { useRef } from "react"; import { toBoundaryError, rejectLiveQueryInput } from "@tanstack/db"; import { useLiveQueryForSuspense } from "./useLiveQuery.js"; import { getLiveQueryResultInfo } from "./live-query-internals.js"; const initialRenderErrors = /* @__PURE__ */ new WeakMap(); function clearInitialRenderError(collection, client) { const entry = initialRenderErrors.get(collection); if (!entry) return; if (client) entry.byClient.delete(client); else delete entry.unscoped; } function rememberInitialRenderError(collection, client, error, clientQuery) { if (collection.status === `cleaned-up`) return; let entry = initialRenderErrors.get(collection); if (!entry) { entry = { byClient: /* @__PURE__ */ new WeakMap() }; collection.once(`status:cleaned-up`, () => { initialRenderErrors.delete(collection); }); initialRenderErrors.set(collection, entry); } if (client) entry.byClient.set(client, { error, clientQuery }); else entry.unscoped = { error }; } function useLiveSuspenseQuery(configOrQueryOrCollection) { const promiseRef = useRef(null); const collectionRef = useRef(null); const hasBeenReadyRef = useRef(false); const result = useLiveQueryForSuspense(configOrQueryOrCollection); if (!result.isEnabled) { throw new Error( `useLiveSuspenseQuery does not support disabled queries (callback returned undefined/null). The Suspense pattern requires data to always be defined (T, not T | undefined). Solutions: 1) Use conditional rendering - don't render the component until the condition is met. 2) Use useLiveQuery instead, which supports disabled queries with the 'isEnabled' flag.` ); } const queryInfo = getLiveQueryResultInfo(result); try { if (collectionRef.current !== result.collection) { promiseRef.current = null; collectionRef.current = result.collection; hasBeenReadyRef.current = false; } const collectionStatus = result.collection.status; if (result.isReady) { hasBeenReadyRef.current = true; promiseRef.current = null; clearInitialRenderError(result.collection, queryInfo.client); } const observerError = queryInfo.observer.getError(); const clientQuery = queryInfo.client && queryInfo.queryHash ? queryInfo.client._getLiveQuery(queryInfo.queryHash) : void 0; if (!hasBeenReadyRef.current && (observerError !== void 0 || clientQuery?.status === `error`)) { promiseRef.current = null; throw observerError === void 0 ? clientQuery?.error : observerError; } if (queryInfo.client?._isSsrStreamingEnabled() && !queryInfo.queryHash) { const reason = queryInfo.identityError ? `${queryInfo.identityError.reason} at ${queryInfo.identityError.path}` : `the query has no stable identity`; throw new Error( `Cannot stream this live query during SSR because ${reason}. Provide an explicit serializable queryKey.` ); } const errorEntry = initialRenderErrors.get(result.collection); const initialRenderError = queryInfo.client ? errorEntry?.byClient.get(queryInfo.client) : errorEntry?.unscoped; if (initialRenderError?.clientQuery !== void 0 && initialRenderError.clientQuery !== clientQuery) { clearInitialRenderError(result.collection, queryInfo.client); } else if (initialRenderError && !hasBeenReadyRef.current) { promiseRef.current = null; throw toBoundaryError(initialRenderError.error); } if (collectionStatus === `crashed` || collectionStatus === `error` && !hasBeenReadyRef.current) { promiseRef.current = null; throw toBoundaryError(result.collection.health.error?.cause); } if (!hasBeenReadyRef.current && (result.isLoading || result.isIdle || result.isLoadingError || result.isCrashed)) { if (!promiseRef.current) { const collection = result.collection; const client = queryInfo.client; const queryHash = queryInfo.queryHash; let active = true; const stopWatchingCleanup = collection.once(`status:cleaned-up`, () => { active = false; }); let preload; try { preload = queryInfo.observer.preload(); } catch (error) { stopWatchingCleanup(); throw error; } const preloadClientQuery = client && queryHash ? client._getLiveQuery(queryHash) : void 0; promiseRef.current = preload.catch((error) => { const latestClientQuery = client && queryHash ? client._getLiveQuery(queryHash) : void 0; if (active && latestClientQuery === preloadClientQuery) rememberInitialRenderError( collection, client, error, preloadClientQuery ); throw error; }).finally(stopWatchingCleanup); } throw promiseRef.current; } return { state: result.state, data: result.data, collection: result.collection, health: result.health }; } catch (error) { if (error instanceof Promise) throw error; return rejectLiveQueryInput(queryInfo.deferredCollections, error); } } export { useLiveSuspenseQuery }; //# sourceMappingURL=useLiveSuspenseQuery.js.map