Skip to content

Add usePaginatedQuery hook to cache helpers #559

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
2 changes: 2 additions & 0 deletions convex/_generated/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type * as addIt from "../addIt.js";
import type * as counter from "../counter.js";
import type * as http from "../http.js";
import type * as migrationsExample from "../migrationsExample.js";
import type * as paginatedQueryExample from "../paginatedQueryExample.js";
import type * as presence from "../presence.js";
import type * as relationshipsExample from "../relationshipsExample.js";
import type * as retriesExample from "../retriesExample.js";
Expand All @@ -38,6 +39,7 @@ declare const fullApi: ApiFromModules<{
counter: typeof counter;
http: typeof http;
migrationsExample: typeof migrationsExample;
paginatedQueryExample: typeof paginatedQueryExample;
presence: typeof presence;
relationshipsExample: typeof relationshipsExample;
retriesExample: typeof retriesExample;
Expand Down
80 changes: 80 additions & 0 deletions convex/paginatedQueryExample.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { query, mutation } from "./_generated/server";
import { v } from "convex/values";
import { paginationOptsValidator } from "convex/server";

/**
* Example of a paginated query that returns users in pages.
*
* This can be used with the usePaginatedQuery hook in the frontend.
*/
export const paginatedUsers = query({
args: {
paginationOpts: paginationOptsValidator,
nameFilter: v.optional(v.string()),
},
handler: async (ctx, args) => {
const { paginationOpts } = args;
const { cursor, numItems = 10 } = paginationOpts;

let usersQuery = ctx.db.query("users");

if (args.nameFilter) {
usersQuery = usersQuery.filter((q) =>
q.eq("name", args.nameFilter ?? ""),
);
}

const orderedQuery = usersQuery.order("asc");

const paginationResult = await orderedQuery.paginate({ cursor, numItems });

return {
page: paginationResult.page,
continueCursor: paginationResult.continueCursor,
isDone: !paginationResult.continueCursor,
};
},
});

/**
* Helper function to create sample users for testing pagination.
*
* This creates a few users with different names to demonstrate pagination.
*/
export const createSampleUsers = mutation({
args: {},
handler: async (ctx) => {
const names = [
"Alice",
"Bob",
"Charlie",
"David",
"Eve",
"Frank",
"Grace",
"Heidi",
"Ivan",
"Judy",
"Kevin",
"Linda",
"Mike",
"Nancy",
"Oscar",
];

const existingUsers = await ctx.db.query("users").collect();

if (existingUsers.length < 5) {
for (const name of names) {
await ctx.db.insert("users", {
name,
age: Math.floor(Math.random() * 50) + 20,
tokenIdentifier: `user:${name.toLowerCase()}`,
});
}
return names.length;
}

return existingUsers.length;
},
});
Loading