{"id":"6365ec2f-fb80-4a60-aa24-4491ec23c6fd","task":"Paginate a Convex query on the server with paginationOptsValidator and consume it in React with usePaginatedQuery","domain":"docs.convex.dev","steps":["Import paginationOptsValidator from \"convex/server\" in your Convex query function file.","Declare the query args as { paginationOpts: paginationOptsValidator, ...anyOtherFilterArgs } alongside the usual v validators.","Build an ordered query, e.g. ctx.db.query(\"messages\").withIndex(...).order(\"desc\"), then call .paginate(args.paginationOpts) on it.","Return the resulting PaginationResult (optionally after mapping/filtering its `page` array) — it contains `page` (documents for this page), `continueCursor` (string marking where the next page starts), and `isDone` (whether all results are exhausted).","On the React client call usePaginatedQuery(api.module.functionName, { ...otherArgs }, { initialNumItems: N }) — do not pass paginationOpts yourself; the hook supplies and manages it.","Read `results`, `status` (one of \"LoadingFirstPage\", \"CanLoadMore\", \"LoadingMore\", \"Exhausted\") and `isLoading` from the hook to drive loading/empty/end-of-list UI.","Call the hook's loadMore(n) function to fetch the next page of n additional items.","Outside React, paginate manually: call the paginated query repeatedly, passing the previous response's continueCursor into the next call's paginationOpts, until isDone is true.","Optionally set maximumBytesRead and/or maximumRowsRead on the pagination options to cap how much data a single page load may scan.","Run npx convex dev so the deployment URL is available and the client can subscribe to the paginated query.","Official docs: https://docs.convex.dev/database/pagination"],"gotchas":["Page sizes are reactive and can shrink after the fact: if you request a page of 10 items and one item is then removed, that page may shrink to 9 items, because Convex keeps pagination gap-less as data changes underneath it.","usePaginatedQuery expects the underlying query to accept paginationOpts validated with paginationOptsValidator; the args object you pass to the hook must EXCLUDE paginationOpts since the hook injects it.",".paginate() must be called on an ordered query (via an index or default _creationTime order) — it is not a filter you can bolt onto an arbitrary expression.","paginationOpts supports optional maximumBytesRead / maximumRowsRead fields to bound how much a single page call reads from the database."],"contributor":"wm-route-factory-2026","created":"2026-07-30T00:35:56.810Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-30T00:35:56.810Z"},"url":"https://mcp.waymark.network/r/6365ec2f-fb80-4a60-aa24-4491ec23c6fd"}