Skip to main content

Reactive Arguments

Re-run a Convex query when filters, route parameters, or selected records change.

Query arguments can be a plain object, a ref, a computed value, or a getter. Nested refs are unwrapped before execution.

Filter a list

ts
const search = ref('')
const includeArchived = ref(false)

const args = computed(() => ({
  search: search.value.trim(),
  includeArchived: includeArchived.value,
}))

const projects = useConvexQuery(api.projects.search, args, {
  keepPreviousData: true,
})

When either input changes, the composable requests the new argument set.

Keep the previous result deliberately

With keepPreviousData: true:

  1. The previous successful data remains visible for the same identity.
  2. pending becomes true for the new arguments.
  3. isStale becomes true.
  4. The new successful result replaces the previous value.
vue
<template>
  <ProjectList :projects="projects.data.value ?? []" :dimmed="projects.isStale.value" />
</template>

The default is false, which clears the old result for an explicit loading transition. An identity generation change always clears old data, regardless of this option.

Skip incomplete arguments

Do not send placeholder IDs:

ts
const args = computed(() => {
  const id = route.params.projectId
  return typeof id === 'string' ? { projectId: id } : 'skip'
})

const project = useConvexQuery(api.projects.get, args)

Use only the literal 'skip'. null is valid Convex data, and undefined represents absent query data; neither is a public skip sentinel.

Auth-dependent execution

Prefer auth: 'required' over reading auth state only to skip a private query:

ts
const projects = useConvexQuery(api.projects.mine, {}, { auth: 'required' })

Use a computed 'skip' when another application condition also determines whether the query is meaningful.

Keep getters pure

Vue may evaluate a computed value more than once. Argument getters should only derive data. Do not navigate, mutate state, or perform network work inside them.