Composables

useConvexPaginatedQuery

Paginate Convex queries with real-time updates.

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.

Usage

app/components/Tasks.vue
<script setup lang="ts">
import { api } from '#convex/api'

const {
  data,
  pages,
  isDone,
  isLoading,
  isLoadingMore,
  loadMore,
  reset,
} = useConvexPaginatedQuery(api.tasks.listPaginated, {}, { numItems: 20 })
</script>

<template>
  <div v-if="isLoading">
    Loading…
  </div>
  <ul v-else>
    <li v-for="task in data" :key="task._id">
      {{ task.title }}
    </li>
  </ul>
  <button :disabled="isDone || isLoadingMore" @click="loadMore">
    Load more
  </button>
  <button @click="reset">
    Reset
  </button>
</template>

Parameters

ParameterTypeDescription
queryFunctionReference<'query'>The paginated Convex query to call.
argsobjectArguments for the query (excluding paginationOpts).
options{ numItems: number }Number of items per page.

Return Values

PropertyTypeDescription
dataComputedRef<T[]>Flattened list of all loaded pages.
pagesComputedRef<T[][]>Array of pages.
lastPageComputedRef<PaginationResult<T> | undefined>Last page result.
isDoneRef<boolean>True when all pages are loaded.
isLoadingComputedRef<boolean>True while the first page is loading.
isLoadingMoreRef<boolean>True while loading additional pages.
loadMore() => voidLoad the next page.
reset() => voidClear pages and reload from the start.
suspense() => Promise<T[][]>Resolves when the first page is available.

Components

nuxt-convex also includes renderless components for template usage:

<ConvexQuery>

<ConvexQuery :query="api.tasks.list" :args="{}">
  <template #loading>Loading…</template>
  <template #error="{ error }">Error: {{ error.message }}</template>
  <template #empty>No tasks yet.</template>
  <template #default="{ data }">
    <ul>
      <li v-for="task in data" :key="task._id">{{ task.title }}</li>
    </ul>
  </template>
</ConvexQuery>

<ConvexPaginatedQuery>

<ConvexPaginatedQuery :query="api.tasks.listPaginated" :args="{}" :options="{ numItems: 20 }">
  <template #loading>Loading…</template>
  <template #error="{ error, reset }">
    <div>Error: {{ error.message }}</div>
    <button @click="reset">Retry</button>
  </template>
  <template #empty>No tasks yet.</template>
  <template #default="{ data, loadMore, isDone }">
    <ul>
      <li v-for="task in data" :key="task._id">{{ task.title }}</li>
    </ul>
    <button :disabled="isDone" @click="loadMore">Load more</button>
  </template>
</ConvexPaginatedQuery>