@tanstack/query-core
Version:
The framework agnostic core that powers TanStack Query
128 lines • 4.04 kB
JavaScript
// src/infiniteQueryBehavior.ts
import { addToEnd, addToStart } from "./utils.js";
function infiniteQueryBehavior(pages) {
return {
onFetch: (context, query) => {
const fetchFn = async () => {
const options = context.options;
const direction = context.fetchOptions?.meta?.fetchMore?.direction;
const oldPages = context.state.data?.pages || [];
const oldPageParams = context.state.data?.pageParams || [];
const empty = { pages: [], pageParams: [] };
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 = context.options.queryFn || (() => Promise.reject(
new Error(`Missing queryFn: '${context.options.queryHash}'`)
));
const fetchPage = async (data, param, previous) => {
if (cancelled) {
return Promise.reject();
}
if (param == null && data.pages.length) {
return Promise.resolve(data);
}
const queryFnContext = {
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)
};
};
let result;
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 {
result = await fetchPage(
empty,
oldPageParams[0] ?? options.initialPageParam
);
const remainingPages = pages ?? oldPages.length;
for (let i = 1; i < remainingPages; i++) {
const param = getNextPageParam(options, result);
result = await fetchPage(result, param);
}
}
return result;
};
if (context.options.persister) {
context.fetchFn = () => {
return context.options.persister?.(
fetchFn,
{
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 options.getNextPageParam(
pages[lastIndex],
pages,
pageParams[lastIndex],
pageParams
);
}
function getPreviousPageParam(options, { pages, pageParams }) {
return options.getPreviousPageParam?.(
pages[0],
pages,
pageParams[0],
pageParams
);
}
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