
Description
Vue 3 bindings for TanStack DB. useLiveQuery composable with MaybeRefOrGetter query functions, ComputedRef return values for all fields (data, state, collection, status, isLoading, isReady, isError). Dependency arrays with Vue refs. Conditional queries via returning undefined/null. Pre-created collection support via ref or getter. Import from @tanstack/vue-db (re-exports all of @tanstack/db).
SKILL.md
This skill builds on db-core. Read it first for collection setup, query builder, and mutation patterns.
TanStack DB — Vue
Setup
<script setup lang="ts">
import { useLiveQuery, eq, not } from '@tanstack/vue-db'
const { data: todos, isLoading } = useLiveQuery((q) =>
q
.from({ todo: todoCollection })
.where(({ todo }) => not(todo.completed))
.orderBy(({ todo }) => todo.created_at, 'asc'),
)
</script>
<template>
<div v-if="isLoading">Loading...</div>
<ul v-else>
<li v-for="todo in todos" :key="todo.id">{{ todo.text }}</li>
</ul>
</template>
@tanstack/vue-db re-exports everything from @tanstack/db.
Hook
useLiveQuery
All return values are ComputedRef:
// Query function with reactive deps
const minPriority = ref(5)
const { data, isLoading, isReady, status } = useLiveQuery(
(q) =>
q
.from({ todo: todoCollection })
.where(({ todo }) => gt(todo.priority, minPriority.value)),
[minPriority],
)
// Config object
const { data } = useLiveQuery({
query: (q) => q.from({ todo: todoCollection }),
gcTime: 60000,
})
// Pre-created collection (reactive via ref)
const { data } = useLiveQuery(preloadedCollection)
// Conditional query
const userId = ref<number | null>(null)
const { data, status } = useLiveQuery(
(q) => {
if (!userId.value) return undefined
return q
.from({ todo: todoCollection })
.where(({ todo }) => eq(todo.userId, userId.value))
},
[userId],
)
Vue-Specific Patterns
Reactive dependencies with refs
const filter = ref('active')
const { data } = useLiveQuery(
(q) =>
q
.from({ todo: todoCollection })
.where(({ todo }) => eq(todo.status, filter.value)),
[filter],
)
// Query re-runs when filter.value changes
Mutations in event handlers
const handleToggle = (id: number) => {
todoCollection.update(id, (draft) => {
draft.completed = !draft.completed
})
}
Includes (Hierarchical Data)
When a query uses includes (subqueries in select), each child field is a live Collection by default. Subscribe to it with useLiveQuery in a subcomponent:
<!-- ProjectList.vue -->
<script setup lang="ts">
import { useLiveQuery, eq } from '@tanstack/vue-db'
const { data: projects } = useLiveQuery((q) =>
q.from({ p: projectsCollection }).select(({ p }) => ({
id: p.id,
name: p.name,
issues: q
.from({ i: issuesCollection })
.where(({ i }) => eq(i.projectId, p.id))
.select(({ i }) => ({ id: i.id, title: i.title })),
})),
)
</script>
<template>
<div v-for="project in projects" :key="project.id">
{{ project.name }}
<IssueList :issues-collection="project.issues" />
</div>
</template>
<!-- IssueList.vue — subscribes to the child Collection -->
<script setup lang="ts">
import { useLiveQuery } from '@tanstack/vue-db'
import type { Collection } from '@tanstack/db'
const props = defineProps<{ issuesCollection: Collection }>()
const { data: issues } = useLiveQuery(() => props.issuesCollection)
</script>
<template>
<ul>
<li v-for="issue in issues" :key="issue.id">{{ issue.title }}</li>
</ul>
</template>
With toArray(), child results are plain arrays and the parent re-emits on child changes:
import { toArray, eq } from '@tanstack/vue-db'
const { data: projects } = useLiveQuery((q) =>
q.from({ p: projectsCollection }).select(({ p }) => ({
id: p.id,
name: p.name,
issues: toArray(
q
.from({ i: issuesCollection })
.where(({ i }) => eq(i.projectId, p.id))
.select(({ i }) => ({ id: i.id, title: i.title })),
),
})),
)
// project.issues is a plain array — no subcomponent needed
See db-core/live-queries/SKILL.md for full includes rules (correlation conditions, nested includes, aggregates).
Common Mistakes
CRITICAL Missing reactive deps in dependency array
Wrong:
const userId = ref(1)
const { data } = useLiveQuery((q) =>
q
.from({ todo: todoCollection })
.where(({ todo }) => eq(todo.userId, userId.value)),
)
Correct:
const userId = ref(1)
const { data } = useLiveQuery(
(q) =>
q
.from({ todo: todoCollection })
.where(({ todo }) => eq(todo.userId, userId.value)),
[userId],
)
Reactive refs used in the query must be included in the deps array for the query to re-run on changes.
Source: docs/framework/vue/overview.md
See also: db-core/live-queries/SKILL.md — for query builder API.
See also: db-core/mutations-optimistic/SKILL.md — for mutation patterns.
More skills from the db repository
View all 13 skillsangular-db
integrate TanStack DB with Angular
Jul 16AngularDatabaseTypeScriptdb-core
manage database collections with TanStack DB
Jul 17Data ModelingDatabaseTanStackdb-core/collection-setup
set up typed collections in TanStack DB
Jul 26Data ModelingDatabaseTanStackdb-core/custom-adapter
build custom TanStack collection adapters
Jul 16DatabaseEngineeringTanStackdb-core/live-queries
build live queries with TanStack DB
Jul 16DatabaseSQLTanStackdb-core/mutations-optimistic
manage optimistic mutations in TanStack DB
Jul 26DatabaseFrontendTanStack
More from TanStack
View publisheraggregation
perform data aggregation in TanStack Table
table
Jul 26Data AnalysisFrontendTanStackapi-not-found
diagnose TanStack Table API errors
table
Jul 26DebuggingFrontendTanStackcell-selection
select rectangular cell ranges in tables
table
Jul 26Data AnalysisTanStackUI Componentsclient-vs-server
manage TanStack Table data pipelines
table
Jul 26Data PipelineFrontendPerformanceTanStackcolumn-faceting
build faceted filter UIs
table
Jul 26Data VisualizationFrontendTanStackcolumn-filtering
implement column filtering in TanStack Table
table
Jul 26Data AnalysisFrontendTanStack