@tanstack/react-db
Version:
React integration for @tanstack/db
156 lines (155 loc) • 5.67 kB
JavaScript
"use client";
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const react = require("react");
const db = require("@tanstack/db");
const DbProvider = require("./DbProvider.cjs");
const useLiveQuery = require("./useLiveQuery.cjs");
const unpreparedQueryValue = /* @__PURE__ */ Symbol(`unpreparedQueryValue`);
function useLiveInfiniteQuery(queryFnOrCollection, config) {
const pageShape = db.readLiveQueryWindowPageShape(config);
const contextDbClient = DbProvider.useOptionalDbClient();
const dbClient = config.client ?? contextDbClient;
const inputIsCollection = db.isCollection(queryFnOrCollection);
const committedRef = react.useRef(null);
const committed = committedRef.current;
const renderedRef = react.useRef(null);
const sourceIdsRef = react.useRef(null);
const derivedIdentityProfilerRef = react.useRef({
renderCount: 0,
totalMs: 0,
maxMs: 0,
warned: false
});
const deferredCollections = /* @__PURE__ */ new Set();
const identityScope = () => useLiveQuery.getIdentityScope(
sourceIdsRef.current ??= db.createLiveQuerySourceIdClaims(),
dbClient,
`useLiveInfiniteQuery`
);
const queryKey = db.getLiveQueryKey(config);
let preparedQueryValue = unpreparedQueryValue;
let dependencies;
let derivedQuery = void 0;
const rendered = renderedRef.current;
let binding;
try {
if (!inputIsCollection) {
if (queryKey !== void 0) {
dependencies = queryKey;
} else if (committed !== null && committed.derivedQuery === queryFnOrCollection && committed.binding.scope === dbClient) {
derivedQuery = queryFnOrCollection;
dependencies = committed.binding.dependencies;
} else {
const preparation = useLiveQuery.prepareDerivedQuery(
queryFnOrCollection,
derivedIdentityProfilerRef.current,
identityScope(),
deferredCollections
);
preparedQueryValue = preparation.value;
derivedQuery = queryFnOrCollection;
dependencies = preparation.identityDeps;
}
}
const compileQuery = () => {
if (preparedQueryValue === unpreparedQueryValue) {
preparedQueryValue = useLiveQuery.prepareQueryValue(
queryFnOrCollection,
dbClient,
deferredCollections
);
}
return preparedQueryValue;
};
binding = db.bindLiveQueryWindow(
committed?.binding ?? null,
{
...pageShape,
input: typeof queryFnOrCollection === `function` ? compileQuery : queryFnOrCollection,
dependencies,
scope: dbClient,
client: dbClient,
queryKey,
recompile: `identity`
},
rendered?.binding
);
} catch (error) {
db.rejectLiveQueryInput(deferredCollections, error);
}
let currentRenderState = committed;
if (binding !== committed?.binding) {
const newCollection = binding.collection !== committed?.binding.collection;
if (newCollection && binding.collection === rendered?.binding.collection) {
for (const deferred of rendered.deferredCollections) {
deferredCollections.add(deferred);
}
}
const reusesRendered = newCollection && binding.collection === rendered?.binding.collection;
currentRenderState = {
binding,
derivedQuery,
deferredCollections,
// A render that never commits releases its deferred sync starts when
// garbage collection reclaims the window collection it built. A reused
// collection keeps the release its first render registered.
cancelReclaimRelease: reusesRendered ? rendered.cancelReclaimRelease : newCollection && binding.ownsCollection ? db.releaseDeferredOnReclaim(binding.collection, deferredCollections) : void 0,
warned: false
};
if (binding.supplied) renderedRef.current = null;
else if (newCollection && binding.ownsCollection) {
renderedRef.current = currentRenderState;
}
}
const renderState = currentRenderState;
const controller = renderState.binding.controller;
const subscribe = react.useCallback(
(onStoreChange) => {
const unsubscribe = controller.subscribe(onStoreChange);
committedRef.current = renderState;
if (renderState.binding.warning && !renderState.warned) {
renderState.warned = true;
console.warn(renderState.binding.warning);
}
renderState.cancelReclaimRelease?.();
db.resumeDeferredLiveQueryCollections(renderState.deferredCollections);
return unsubscribe;
},
[controller, renderState]
);
const getSnapshot = react.useCallback(() => controller.getSnapshot(), [controller]);
const snapshot = react.useSyncExternalStore(
subscribe,
getSnapshot,
() => controller.getServerSnapshot()
);
const fetchNextPage = react.useCallback(
() => db.fetchNextLiveQueryWindowPage(controller),
[controller]
);
return {
data: snapshot.data,
get state() {
return snapshot.state;
},
status: snapshot.status,
isLoading: snapshot.isLoading,
isReady: snapshot.isReady,
isIdle: snapshot.isIdle,
isLoadingError: snapshot.isLoadingError,
isCrashed: snapshot.isCrashed,
isCleanedUp: snapshot.isCleanedUp,
isSyncError: snapshot.isSyncError,
collection: snapshot.collection,
isEnabled: snapshot.isEnabled,
pages: snapshot.pages,
pageParams: snapshot.pageParams,
fetchNextPage,
hasNextPage: snapshot.hasNextPage,
isFetchingNextPage: snapshot.isFetchingNextPage,
health: snapshot.health
};
}
exports.useLiveInfiniteQuery = useLiveInfiniteQuery;
//# sourceMappingURL=useLiveInfiniteQuery.cjs.map