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
const search = ref('')
const includeArchived = ref(false)
const args = computed(() => ({
search: search.value.trim(),
includeArchived: includeArchived.value,
}))
const projects = await 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:
- The previous successful
dataremains visible. pendingbecomes true for the new arguments.isStalebecomes true.- The new successful result replaces the previous value.
<template>
<ProjectList :projects="projects.data.value ?? []" :dimmed="projects.isStale.value" />
</template>The default is false, which clears the old result for a more explicit loading transition.
Skip incomplete arguments
Do not send placeholder IDs:
const args = computed(() => {
const id = route.params.projectId
return typeof id === 'string' ? { projectId: id } : 'skip'
})
const project = await useConvexQuery(api.projects.get, args)Use only the literal 'skip'. null and undefined are not public skip sentinels.
Auth-dependent execution
Prefer auth: 'required' over manually reading auth state only to skip a private query:
const projects = await useConvexQuery(
api.projects.mine,
{},
{
auth: 'required',
},
)Use a computed 'skip' when another application condition also determines whether the query is meaningful.
Avoid side effects in argument getters
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.