|
| 1 | +--- |
| 2 | +title: useConvexPaginatedQuery |
| 3 | +description: Paginate Convex queries with real-time updates. |
| 4 | +--- |
| 5 | + |
| 6 | +Paginate a Convex query that returns a `PaginationResult`. This composable is **client-only** and subscribes to real-time updates. For SSR, use `useConvexQuery` and fetch a single page on the server. |
| 7 | + |
| 8 | +## Usage |
| 9 | + |
| 10 | +```vue [app/components/Tasks.vue] |
| 11 | +<script setup lang="ts"> |
| 12 | +import { api } from '#convex/api' |
| 13 | +
|
| 14 | +const { |
| 15 | + data, |
| 16 | + pages, |
| 17 | + isDone, |
| 18 | + isLoading, |
| 19 | + isLoadingMore, |
| 20 | + loadMore, |
| 21 | + reset, |
| 22 | +} = useConvexPaginatedQuery(api.tasks.listPaginated, {}, { numItems: 20 }) |
| 23 | +</script> |
| 24 | +
|
| 25 | +<template> |
| 26 | + <div v-if="isLoading"> |
| 27 | + Loading… |
| 28 | + </div> |
| 29 | + <ul v-else> |
| 30 | + <li v-for="task in data" :key="task._id"> |
| 31 | + {{ task.title }} |
| 32 | + </li> |
| 33 | + </ul> |
| 34 | + <button :disabled="isDone || isLoadingMore" @click="loadMore"> |
| 35 | + Load more |
| 36 | + </button> |
| 37 | + <button @click="reset"> |
| 38 | + Reset |
| 39 | + </button> |
| 40 | +</template> |
| 41 | +``` |
| 42 | + |
| 43 | +## Parameters |
| 44 | + |
| 45 | +| Parameter | Type | Description | |
| 46 | +| --------- | ---------------------------- | ----------------------------------------------------- | |
| 47 | +| `query` | `FunctionReference<'query'>` | The paginated Convex query to call. | |
| 48 | +| `args` | `object` | Arguments for the query (excluding `paginationOpts`). | |
| 49 | +| `options` | `{ numItems: number }` | Number of items per page. | |
| 50 | + |
| 51 | +## Return Values |
| 52 | + |
| 53 | +| Property | Type | Description | |
| 54 | +| --------------- | ----------------------------------------------- | ------------------------------------------ | |
| 55 | +| `data` | `ComputedRef<T[]>` | Flattened list of all loaded pages. | |
| 56 | +| `pages` | `ComputedRef<T[][]>` | Array of pages. | |
| 57 | +| `lastPage` | `ComputedRef<PaginationResult<T> \| undefined>` | Last page result. | |
| 58 | +| `isDone` | `Ref<boolean>` | True when all pages are loaded. | |
| 59 | +| `isLoading` | `ComputedRef<boolean>` | True while the first page is loading. | |
| 60 | +| `isLoadingMore` | `Ref<boolean>` | True while loading additional pages. | |
| 61 | +| `loadMore` | `() => void` | Load the next page. | |
| 62 | +| `reset` | `() => void` | Clear pages and reload from the start. | |
| 63 | +| `suspense` | `() => Promise<T[][]>` | Resolves when the first page is available. | |
| 64 | + |
| 65 | +## Components |
| 66 | + |
| 67 | +`nuxt-convex` also includes renderless components for template usage: |
| 68 | + |
| 69 | +### `<ConvexQuery>` |
| 70 | + |
| 71 | +```vue |
| 72 | +<ConvexQuery :query="api.tasks.list" :args="{}"> |
| 73 | + <template #loading>Loading…</template> |
| 74 | + <template #error="{ error }">Error: {{ error.message }}</template> |
| 75 | + <template #empty>No tasks yet.</template> |
| 76 | + <template #default="{ data }"> |
| 77 | + <ul> |
| 78 | + <li v-for="task in data" :key="task._id">{{ task.title }}</li> |
| 79 | + </ul> |
| 80 | + </template> |
| 81 | +</ConvexQuery> |
| 82 | +``` |
| 83 | + |
| 84 | +### `<ConvexPaginatedQuery>` |
| 85 | + |
| 86 | +```vue |
| 87 | +<ConvexPaginatedQuery :query="api.tasks.listPaginated" :args="{}" :options="{ numItems: 20 }"> |
| 88 | + <template #loading>Loading…</template> |
| 89 | + <template #error="{ error, reset }"> |
| 90 | + <div>Error: {{ error.message }}</div> |
| 91 | + <button @click="reset">Retry</button> |
| 92 | + </template> |
| 93 | + <template #empty>No tasks yet.</template> |
| 94 | + <template #default="{ data, loadMore, isDone }"> |
| 95 | + <ul> |
| 96 | + <li v-for="task in data" :key="task._id">{{ task.title }}</li> |
| 97 | + </ul> |
| 98 | + <button :disabled="isDone" @click="loadMore">Load more</button> |
| 99 | + </template> |
| 100 | +</ConvexPaginatedQuery> |
| 101 | +``` |
0 commit comments