关于 tanstack-db
tanstack-db 是介绍 TanStack DB 的 Skill;TanStack DB 是基于差分数据流的客户端嵌入式数据库层,目前处于 Beta 阶段。内容涵盖规范化集合、响应式实时查询、乐观变更,以及与 TanStack Query 和多种数据源的集成。
主要功能
- 01适配多种数据源的规范化集合
- 02类 SQL 构造器的响应式实时查询
- 03自动乐观更新与失败回滚
- 04增量式查询计算
- 05主动和按需同步模式
适用场景
- 01在客户端应用中构建响应式数据视图
- 02变更同步时立即更新界面
- 03查询和连接规范化集合
- 04按需加载大型集合
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ tanstack-skills/ tanstack-skills --skill tanstack-db安装后在 Claude Code 中输入/tanstack-db确认已加载。
详细介绍
概述
TanStack DB 是一个基于差分数据流构建的客户端嵌入式数据库层。它维护规范化集合,使用增量计算执行实时查询,提供自动乐观更新,并与 TanStack Query 集成以获取数据。即使处理 10 万多行数据,更新也能在亚毫秒级完成。
软件包: @tanstack/react-db
查询集成: @tanstack/query-db-collection
状态: Beta(v0.5)
安装
npm install @tanstack/react-db @tanstack/query-db-collection
核心概念
- 集合:封装数据源(TanStack Query、Electric 等)的规范化数据存储
- 实时查询:使用类 SQL 查询构建器的响应式订阅
- 乐观更新:失败时自动即时更新 UI 并回滚
- 差分数据流:发生更改时仅重新计算受影响的查询结果
集合
创建集合
import { createCollection } from '@tanstack/react-db'
import { queryCollectionOptions } from '@tanstack/query-db-collection'
const todoCollection = createCollection(
queryCollectionOptions({
queryKey: ['todos'],
queryFn: async () => api.todos.getAll(),
getKey: (item) => item.id,
schema: todoSchema,
onInsert: async ({ transaction }) => {
await Promise.all(
transaction.mutations.map((mutation) =>
api.todos.create(mutation.modified)
)
)
},
onUpdate: async ({ transaction }) => {
await Promise.all(
transaction.mutations.map((mutation) =>
api.todos.update(mutation.modified)
)
)
},
onDelete: async ({ transaction }) => {
await Promise.all(
transaction.mutations.map((mutation) =>
api.todos.delete(mutation.original.id)
)
)
},
})
)
同步模式
// Eager (default): Load entire collection upfront. Best for <10k rows.
const smallCollection = createCollection(
queryCollectionOptions({ syncMode: 'eager', /* ... */ })
)
// On-Demand: Load only what queries request. Best for >50k rows, search.
const largeCollection = createCollection(
queryCollectionOptions({
syncMode: 'on-demand',
queryFn: async (ctx) => {
const params = parseLoadSubsetOptions(ctx.meta?.loadSubsetOptions)
return api.getProducts(params)
},
})
)
// Progressive: Load query subset immediately, full sync in background.
const collaborativeCollection = createCollection(
queryCollectionOptions({ syncMode: 'progressive', /* ... */ })
)
实时查询
基本查询
import { useLiveQuery } from '@tanstack/react-db'
import { eq } from '@tanstack/db'
function TodoList() {
const { data: todos } = useLiveQuery((query) =>
query
.from({ todos: todoCollection })
.where(({ todos }) => eq(todos.completed, false))
)
return <ul>{todos.map(todo => <li key={todo.id}>{todo.text}</li>)}</ul>
}
查询构建器 API
const { data } = useLiveQuery((q) =>
q
.from({ t: todoCollection })
.where(({ t }) => eq(t.status, 'active'))
.orderBy(({ t }) => t.createdAt, 'desc')
.limit(10)
)
联接
const { data } = useLiveQuery((q) =>
q
.from({ t: todoCollection })
.innerJoin(
{ u: userCollection },
({ t, u }) => eq(t.userId, u.id)
)
.innerJoin(
{ p: projectCollection },
({ u, p }) => eq(u.projectId, p.id)
)
.where(({ p }) => eq(p.id, currentProject.id))
)
筛选运算符
import { eq, lt, and } from '@tanstack/db'
// Equality
eq(field, value)
// Less than
lt(field, value)
// AND
and(eq(product.category, 'electronics'), lt(product.price, 100))
排序和限制
const { data } = useLiveQuery((q) =>
q
.from({ product: productsCollection })
.where(({ product }) =>
and(eq(product.category, 'electronics'), lt(product.price, 100))
)
.orderBy(({ product }) => product.price, 'asc')
.limit(10)
)
乐观更新
插入
todoCollection.insert({
id: uuid(),
text: 'New todo',
completed: false,
})
// Immediately: updates all live queries referencing this collection
// Background: calls onInsert handler to sync with server
// On failure: automatic rollback
无需手动编写样板代码
| 之前(仅使用 TanStack Query) | 之后(TanStack DB) |
|---|---|
手动使用 onMutate 管理乐观状态 | 自动 |
手动编写 onError 回滚逻辑 | 自动 |
| 每次更新都要失效缓存 | 所有实时查询都会自动更新 |
查询驱动同步(按需)
实时查询会自动生成经过优化的网络请求:
// This live query...
useLiveQuery((q) =>
q.from({ product: productsCollection })
.where(({ product }) => and(eq(product.category, 'electronics'), lt(product.price, 100)))
.orderBy(({ product }) => product.price, 'asc')
.limit(10)
)
// ...automatically generates:
// GET /api/products?category=electronics&price_lt=100&sort=price:asc&limit=10
谓词映射
queryFn: async (ctx) => {
const { filters, sorts, limit } = parseLoadSubsetOptions(ctx.meta?.loadSubsetOptions)
const params = new URLSearchParams()
filters.forEach(({ field, operator, value }) => {
if (operator === 'eq') params.set(field.join('.'), String(value))
else if (operator === 'lt') params.set(`${field.join('.')}_lt`, String(value))
})
if (limit) params.set('limit', String(limit))
return fetch(`/api/products?${params}`).then(r => r.json())
}
性能
| 操作 | 延迟 |
|---|---|
| 更新单行(10 万行已排序的集合) | ~0.7 ms |
| 后续查询(同步后) | <1 ms |
| 跨集合联接 | 亚毫秒级 |
支持的集合类型
- Query 集合 - TanStack Query 集成
- Electric 集合 - Electric SQL 实时同步
- TrailBase 集合 - TrailBase 后端
- RxDB 集合 - RxDB 集成
- PowerSync 集合 - PowerSync 同步
- LocalStorage 集合 - 浏览器持久化
- LocalOnly 集合 - 仅内存存储
API 摘要
import { createCollection, useLiveQuery } from '@tanstack/react-db'
import { queryCollectionOptions } from '@tanstack/query-db-collection'
import { eq, lt, and, parseLoadSubsetOptions } from '@tanstack/db'
最佳实践
- 在模块级别定义集合 - 集合是单例
- 选择合适的同步模式:
eager(<1 万条)、on-demand(>5 万条)、progressive(协作场景) - 使用联接而非视图专用 API - 一次性加载规范化集合
- 让 TanStack Query 负责数据获取 - DB 扩展 Query,而不是取代它
- 使用
parseLoadSubsetOptions将实时查询谓词映射为 API 参数 - 依赖自动乐观更新 - 不要手动管理乐观状态
- 使用模式进行运行时验证和 TypeScript 类型推断
- 利用增量计算 - 让引擎处理筛选,而不是手动调用
.filter()
常见问题
- 在组件内创建集合(应在模块级别创建)
- 试图完全取代 TanStack Query(DB 构建于其之上)
- 在渲染期间手动调用
.filter(),而不是使用实时查询的where子句 - 未提供
getKey以正确规范化数据 - 忘记用于服务器同步的更新处理器(
onInsert、onUpdate、onDelete)
评论
支持 Markdown