@tanstack/query-core
Version:
The framework agnostic core that powers TanStack Query
121 lines • 4.13 kB
JavaScript
// src/infiniteQueryBehavior.ts
import { addToEnd, addToStart, ensureQueryFn } from "./utils.js";
function infiniteQueryBehavior(pages) {
return {
onFetch: (context, query) => {
const options = context.options;
const direction = context.fetchOptions?.meta?.fetchMore?.direction;
const oldPages = context.state.data?.pages || [];
const oldPageParams = context.state.data?.pageParams || [];
let result = { pages: [], pageParams: [] };
let currentPage = 0;
const fetchFn = async () => {
let cancelled = false;
const addSignalProperty = (object) => {
Object.defineProperty(object, "signal", {
enumerable: true,
get: () => {
if (context.signal.aborted) {
cancelled = true;
} else {
context.signal.addEventListener("abort", () => {
cancelled = true;
});
}
return context.signal;
}
});
};
const queryFn = ensureQueryFn(context.options, context.fetchOptions);
const fetchPage = async (data, param, previous) => {
if (cancelled) {
return Promise.reject();
}
if (param == null && data.pages.length) {
return Promise.resolve(data);
}
const queryFnContext = {
client: context.client,
queryKey: context.queryKey,
pageParam: param,
direction: previous ? "backward" : "forward",
meta: context.options.meta
};
addSignalProperty(queryFnContext);
const page = await queryFn(
queryFnContext
);
const { maxPages } = context.options;
const addTo = previous ? addToStart : addToEnd;
return {
pages: addTo(data.pages, page, maxPages),
pageParams: addTo(data.pageParams, param, maxPages)
};
};
if (direction && oldPages.length) {
const previous = direction === "backward";
const pageParamFn = previous ? getPreviousPageParam : getNextPageParam;
const oldData = {
pages: oldPages,
pageParams: oldPageParams
};
const param = pageParamFn(options, oldData);
result = await fetchPage(oldData, param, previous);
} else {
const remainingPages = pages ?? oldPages.length;
do {
const param = currentPage === 0 ? oldPageParams[0] ?? options.initialPageParam : getNextPageParam(options, result);
if (currentPage > 0 && param == null) {
break;
}
result = await fetchPage(result, param);
currentPage++;
} while (currentPage < remainingPages);
}
return result;
};
if (context.options.persister) {
context.fetchFn = () => {
return context.options.persister?.(
fetchFn,
{
client: context.client,
queryKey: context.queryKey,
meta: context.options.meta,
signal: context.signal
},
query
);
};
} else {
context.fetchFn = fetchFn;
}
}
};
}
function getNextPageParam(options, { pages, pageParams }) {
const lastIndex = pages.length - 1;
return pages.length > 0 ? options.getNextPageParam(
pages[lastIndex],
pages,
pageParams[lastIndex],
pageParams
) : void 0;
}
function getPreviousPageParam(options, { pages, pageParams }) {
return pages.length > 0 ? options.getPreviousPageParam?.(pages[0], pages, pageParams[0], pageParams) : void 0;
}
function hasNextPage(options, data) {
if (!data) return false;
return getNextPageParam(options, data) != null;
}
function hasPreviousPage(options, data) {
if (!data || !options.getPreviousPageParam) return false;
return getPreviousPageParam(options, data) != null;
}
export {
hasNextPage,
hasPreviousPage,
infiniteQueryBehavior
};
//# sourceMappingURL=infiniteQueryBehavior.js.map