convex
Version:
Client for the Convex Cloud
122 lines (121 loc) • 3.69 kB
JavaScript
;
import { convexToJson } from "../values/index.js";
import { useMemo, useState } from "react";
import { useQueriesGeneric } from "./use_queries.js";
export function usePaginatedQueryGeneric(name, options, ...args) {
const createInitialState = useMemo(() => {
return () => {
const id = nextPaginationId();
return {
name,
args,
id,
maxQueryIndex: 0,
queries: {
0: {
name,
args: [
{
numItems: options.initialNumItems,
cursor: null,
id
},
...args
]
}
}
};
};
}, [JSON.stringify(convexToJson(args)), name, options.initialNumItems]);
const [state, setState] = useState(createInitialState);
let currState = state;
if (name !== state.name || JSON.stringify(convexToJson(args)) !== JSON.stringify(convexToJson(state.args))) {
currState = createInitialState();
setState(currState);
}
const resultsObject = useQueriesGeneric(currState.queries);
const [results, maybeLastResult] = useMemo(() => {
let currResult = void 0;
const allItems = [];
for (let i = 0; i <= currState.maxQueryIndex; i++) {
currResult = resultsObject[i];
if (currResult === void 0) {
break;
}
if (currResult instanceof Error) {
if (currResult.message.includes("InvalidCursor") || currResult.message.includes("QueryScannedTooManyDocuments")) {
setState(createInitialState);
return [[], void 0];
} else {
throw currResult;
}
}
allItems.push(...currResult.page);
}
return [allItems, currResult];
}, [resultsObject, currState.maxQueryIndex, createInitialState]);
const statusAndLoadMore = useMemo(() => {
if (maybeLastResult === void 0) {
return {
status: "LoadingMore",
loadMore: void 0
};
}
if (maybeLastResult.isDone) {
return {
status: "Exhausted",
loadMore: void 0
};
}
const continueCursor = maybeLastResult.continueCursor;
let alreadyLoadingMore = false;
return {
status: "CanLoadMore",
loadMore: (numItems) => {
if (!alreadyLoadingMore) {
alreadyLoadingMore = true;
setState((prevState) => {
const maxQueryIndex = prevState.maxQueryIndex + 1;
const queries = { ...prevState.queries };
queries[maxQueryIndex] = {
name: prevState.name,
args: [
{ numItems, cursor: continueCursor, id: prevState.id },
...prevState.args
]
};
return {
...prevState,
maxQueryIndex,
queries
};
});
}
}
};
}, [maybeLastResult]);
return {
results,
...statusAndLoadMore
};
}
let paginationId = 0;
function nextPaginationId() {
paginationId++;
return paginationId;
}
export function optimisticallyUpdateValueInPaginatedQuery(localStore, name, args, updateValue) {
const expectedArgs = JSON.stringify(convexToJson(args));
for (const query of localStore.getAllQueries(name)) {
if (query.value !== void 0 && query.args.length >= 1 && JSON.stringify(convexToJson(query.args.slice(1))) === expectedArgs) {
const value = query.value;
if (typeof value === "object" && value !== null && Array.isArray(value.page)) {
localStore.setQuery(name, query.args, {
...value,
page: value.page.map(updateValue)
});
}
}
}
}
//# sourceMappingURL=use_paginated_query.js.map