Skip to content

Commit cee4078

Browse files
ianmacartneyConvex, Inc.
authored and
Convex, Inc.
committed
usePaginatedQuery uses latestPageSize option (#37894)
GitOrigin-RevId: 2fad45fb7b9589f847c76ed63bad452be373b96b
1 parent ba821c0 commit cee4078

File tree

2 files changed

+63
-79
lines changed

2 files changed

+63
-79
lines changed

npm-packages/convex/src/react/use_paginated_query.test.tsx

Lines changed: 51 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -277,69 +277,62 @@ describe("usePaginatedQuery pages", () => {
277277

278278
test.each([
279279
{
280-
endCursorBehavior: undefined,
280+
latestPageSize: undefined,
281281
},
282282
{
283-
endCursorBehavior: "setOnLoadMore" as const,
283+
latestPageSize: "fixed" as const,
284284
},
285285
{
286-
endCursorBehavior: "legacyQueryJournal" as const,
286+
latestPageSize: "grow" as const,
287287
},
288-
])(
289-
"loadMore with endCursorBehavior $endCursorBehavior",
290-
({ endCursorBehavior }) => {
291-
const { result } = renderHook(
292-
() =>
293-
usePaginatedQuery(
294-
query,
295-
{},
296-
{ initialNumItems: 1, endCursorBehavior },
297-
),
298-
{ wrapper },
299-
);
300-
mockPage(
301-
{
302-
numItems: 1,
303-
cursor: null,
304-
},
305-
{
306-
page: ["item1"],
307-
continueCursor: "abc",
308-
isDone: false,
309-
},
310-
);
311-
mockPage(
312-
{
313-
numItems: 1,
314-
cursor: null,
315-
endCursor: "abc",
316-
},
317-
{
318-
page: ["item1"],
319-
continueCursor: "abc",
320-
isDone: false,
321-
},
322-
);
323-
mockPage(
324-
{
325-
numItems: 2,
326-
cursor: "abc",
327-
},
328-
{
329-
page: ["item2"],
330-
continueCursor: "def",
331-
isDone: true,
332-
},
333-
);
334-
expect(result.current.status).toStrictEqual("CanLoadMore");
335-
expect(result.current.results).toStrictEqual(["item1"]);
336-
act(() => {
337-
result.current.loadMore(2);
338-
});
339-
expect(result.current.status).toStrictEqual("Exhausted");
340-
expect(result.current.results).toStrictEqual(["item1", "item2"]);
341-
},
342-
);
288+
])("loadMore with latestPageSize $latestPageSize", ({ latestPageSize }) => {
289+
const { result } = renderHook(
290+
() =>
291+
usePaginatedQuery(query, {}, { initialNumItems: 1, latestPageSize }),
292+
{ wrapper },
293+
);
294+
mockPage(
295+
{
296+
numItems: 1,
297+
cursor: null,
298+
},
299+
{
300+
page: ["item1"],
301+
continueCursor: "abc",
302+
isDone: false,
303+
},
304+
);
305+
mockPage(
306+
{
307+
numItems: 1,
308+
cursor: null,
309+
endCursor: "abc",
310+
},
311+
{
312+
page: ["item1"],
313+
continueCursor: "abc",
314+
isDone: false,
315+
},
316+
);
317+
mockPage(
318+
{
319+
numItems: 2,
320+
cursor: "abc",
321+
},
322+
{
323+
page: ["item2"],
324+
continueCursor: "def",
325+
isDone: true,
326+
},
327+
);
328+
expect(result.current.status).toStrictEqual("CanLoadMore");
329+
expect(result.current.results).toStrictEqual(["item1"]);
330+
act(() => {
331+
result.current.loadMore(2);
332+
});
333+
expect(result.current.status).toStrictEqual("Exhausted");
334+
expect(result.current.results).toStrictEqual(["item1", "item2"]);
335+
});
343336

344337
test("single page updating", () => {
345338
const { result } = renderHook(

npm-packages/convex/src/react/use_paginated_query.ts

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -153,22 +153,13 @@ const completeSplitQuery =
153153
* @param args - The arguments object for the query function, excluding
154154
* the `paginationOpts` property. That property is injected by this hook.
155155
* @param options - An object specifying the `initialNumItems` to be loaded in
156-
* the first page, and the `endCursorBehavior` to use.
157-
* @param options.endCursorBehavior` controls how the `endCursor` is set on the
158-
* last loaded page. The current behavior is to have the first request for a page
159-
* "pin" the end of the page to the `endCursor` returned in the first request.
160-
* This shows up as your first request growing as new items are added within
161-
* the range of the initial page. This is tracked via a QueryJournal, which is
162-
* not shared between clients and can have unexpected behavior, so we will be
163-
* deprecating this behavior in favor of the new option `setOnLoadMore`.
164-
* For `setOnLoadMore`, the `endCursor` is not inferred from the first request,
165-
* instead the first call to `loadMore` will explicitly set the `endCursor` to
166-
* the `continueCursor` of the last page. In the future this will not use the
167-
* QueryJournal and will become the default behavior, resulting in the first
168-
* page staying at the same size as `initialNumItems` until you call `loadMore`.
169-
* Note: setting the `endCursor` on the request will re-request that page with
170-
* the new argument, causing an effectively duplicate request per `loadMore`.
171-
*
156+
* the first page, and the `latestPageSize` to use.
157+
* @param options.latestPageSize controls how the latest page (the first page
158+
* until another page is loaded) size grows. With "fixed", the page size will
159+
* stay at the size specified by `initialNumItems` / `loadMore`. With "grow",
160+
* the page size will grow as new items are added within the range of the initial
161+
* page. Once multiple pages are loaded, all but the last page will grow, in
162+
* order to provide seamless pagination. See the docs for more details.
172163
* @returns A {@link UsePaginatedQueryResult} that includes the currently loaded
173164
* items, the status of the pagination, and a `loadMore` function.
174165
*
@@ -179,7 +170,7 @@ export function usePaginatedQuery<Query extends PaginatedQueryReference>(
179170
args: PaginatedQueryArgs<Query> | "skip",
180171
options: {
181172
initialNumItems: number;
182-
endCursorBehavior?: "setOnLoadMore" | "legacyQueryJournal";
173+
latestPageSize?: "grow" | "fixed";
183174
},
184175
): UsePaginatedQueryReturnType<Query> {
185176
if (
@@ -256,9 +247,9 @@ export function usePaginatedQuery<Query extends PaginatedQueryReference>(
256247
Value[],
257248
undefined | PaginationResult<Value>,
258249
] = useMemo(() => {
259-
let currResult = undefined;
250+
let currResult: PaginationResult<Value> | undefined = undefined;
260251

261-
const allItems = [];
252+
const allItems: Value[] = [];
262253
for (const pageKey of currState.pageKeys) {
263254
currResult = resultsObject[pageKey];
264255
if (currResult === undefined) {
@@ -375,7 +366,7 @@ export function usePaginatedQuery<Query extends PaginatedQueryReference>(
375366
const queries = { ...prevState.queries };
376367
let ongoingSplits = prevState.ongoingSplits;
377368
let pageKeys = prevState.pageKeys;
378-
if (options.endCursorBehavior === "setOnLoadMore") {
369+
if (options.latestPageSize === "fixed") {
379370
const lastPageKey = prevState.pageKeys.at(-1)!;
380371
const boundLastPageKey = nextPageKey;
381372
queries[boundLastPageKey] = {
@@ -420,7 +411,7 @@ export function usePaginatedQuery<Query extends PaginatedQueryReference>(
420411
}
421412
},
422413
} as const;
423-
}, [maybeLastResult, currState.nextPageKey, options.endCursorBehavior]);
414+
}, [maybeLastResult, currState.nextPageKey, options.latestPageSize]);
424415

425416
return {
426417
results,

0 commit comments

Comments
 (0)