DB 与 Pacer:新库概览
本教程共 38 篇 · 第 38 篇 · 更新于 2026-07-27 · 约 11 分钟阅读
38. DB 与 Pacer:新库概览
本节目标:了解 TanStack 生态的两个新库。TanStack DB(客户端数据库、live queries、乐观更新)和 TanStack Pacer(防抖、节流、限流、队列),顺带认识 Ranger,展望生态未来。学完你对 TanStack 全生态有完整认知。
38.1 TanStack DB:客户端数据库
前面 37 章讲的库都是成熟稳定的。这一章讲的两个库还处于 v0 阶段,API 可能变动,但方向已经清晰。
WarningTanStack DB 当前版本 v0.1.x,属于早期阶段。API 可能变动,本章内容基于 2026 年 7 月的公开信息,实际使用时请查阅最新文档。
38.1.1 DB 解决什么问题
你已经会了 TanStack Query:它管服务端数据的获取、缓存、失效。但 Query 有个短板—它把每次查询的结果当成独立的数据块,查询之间没有关系。
打个比方:Query 像是你从仓库取了一堆东西放到不同的柜子里。但你想知道「所有未完成的任务属于哪个项目」,就得自己手动翻柜子、做关联、过滤。数据量一大,前端 filter()/find()/useMemo() 满天飞,渲染卡顿。
TanStack DB 的答案是:在浏览器里放一个客户端数据库。数据进来后存成归一化的集合(Collection),然后用类似 SQL 的查询语句做关联、过滤、聚合,而且查询结果是**响应式(Live)**的—底层数据变了,查询结果自动更新。
官方的说法是:Query 管「数据怎么拿」,DB 管「数据来了之后怎么保持一致和快速」。
38.1.2 核心概念
TanStack DB 有三个核心概念:
集合(Collections):把你的 useQuery 调用包装成集合。REST、GraphQL、WebSocket 都行,数据进来后存成归一化的表。
import { createCollection } from '@tanstack/react-db'
import { queryCollectionOptions } from '@tanstack/query-db-collection'
const todoCollection = createCollection(
queryCollectionOptions({
queryKey: ['todos'],
queryFn: async () => fetchTodos(),
getKey: (item) => item.id, // 每条数据的唯一标识
schema: todoSchema, // 数据结构定义(用 Zod 等)
})
)
实时查询(Live Queries):类似 SQL 的查询语句,跨集合做关联、过滤、聚合。查询结果是响应式的,底层数据变了自动更新。
import { useLiveQuery } from '@tanstack/react-db'
import { eq } from '@tanstack/db'
function TodoList() {
// 查询未完成的任务,数据变化时自动更新
const { data: pendingTodos } = useLiveQuery((query) =>
query
.from({ todos: todoCollection })
.where(({ todos }) => eq(todos.completed, false))
)
return <List items={pendingTodos} />
}
乐观变更(Optimistic Mutations):直接往集合里写数据,DB 自动做乐观更新。失败了自动回滚,不用手写 onMutate/onError/onSettled 那套。
// 一行搞定,自动乐观更新、自动回滚
todoCollection.insert({
id: crypto.randomUUID(),
text: '新任务',
completed: false,
})
38.1.3 为什么快:差分数据流(Differential Dataflow)
DB 的性能秘诀是差分数据流(Differential Dataflow)。简单说就是:数据变化时,不重新计算整个查询结果,只算变化的那部分。
举个例子:你有 10 万条任务,其中 1000 条是未完成的。你勾选了一条变成已完成,传统做法是重新过滤 10 万条数据。差分数据流只更新那 1 条的变化,其他 999 条未完成的不受影响,几乎零开销。
官方的数据:更新 10 万行数据中的一行,0.7 毫秒搞定。这是在浏览器里跑的,不是服务端。
Tip差分数据流不是 TanStack 发明的,它来自数据库领域的研究。TanStack DB 把这个技术搬到了浏览器里,让前端也能享受数据库级别的查询性能。
38.1.4 和 Query 的关系
DB 不是替代 Query 的,而是在 Query 之上加了一层:
服务端 API
↓ useQuery(Query 管:获取、缓存、失效)
TanStack Query 缓存
↓ createCollection(DB 管:归一化、关联、响应式查询)
TanStack DB 集合
↓ useLiveQuery
组件渲染
Query 负责把数据从服务端拉到浏览器,DB 负责把数据组织好、查询好、保持一致。你可以一个集合一个集合地逐步引入,不用一次性改造整个项目。
NoteDB 适合数据量大、关联复杂、需要实时更新的场景。如果只是简单的 CRUD,用 Query 就够了。数据量上千、有跨表关联、乐观更新频繁时,DB 的价值才明显。
38.2 TanStack Pacer:时间控制工具箱
WarningTanStack Pacer 当前版本 v0.22.x,属于 v0 阶段。API 可能变动,本章内容基于 2026 年 7 月的公开信息。
38.2.1 Pacer 解决什么问题
前端开发里有一类问题特别烦:事件太频繁,处理跟不上。
- 用户输入搜索框,每输一个字符发一次请求—服务端被刷爆。
- 监听
scroll事件,滚动一秒触发几十次—页面卡顿。 - 上传文件,同时开太多并发—浏览器和服务器都扛不住。
以前你得自己写 setTimeout 防抖、Date.now() 节流、Promise.all 限流… 每个项目重复造轮子。
TanStack Pacer 把这些时间控制逻辑封装成类型安全的基础工具:防抖(Debounce)、节流(Throttle)、限流(Rate Limiting)、队列(Queuing)、批量处理(Batching)。
38.2.2 五大核心能力
防抖(Debounce):事件停了才执行。适合搜索框、自动保存、表单校验。
import { useDebouncedCallback } from '@tanstack/react-pacer'
function SearchBox() {
// 用户停止输入 500ms 后才执行搜索
const debouncedSearch = useDebouncedCallback(
(value: string) => {
searchAPI(value)
},
{ wait: 500 }
)
return <input onChange={(e) => debouncedSearch(e.target.value)} />
}
节流(Throttle):固定间隔执行一次。适合滚动、缩放、指针移动。
import { useThrottledCallback } from '@tanstack/react-pacer'
function ScrollHandler() {
// 每 100ms 最多执行一次
const throttledScroll = useThrottledCallback(
(scrollY: number) => {
updateScrollPosition(scrollY)
},
{ wait: 100 }
)
return <div onScroll={(e) => throttledScroll(e.currentTarget.scrollTop)} />
}
限流(Rate Limiting):限制时间窗口内的执行次数。适合 API 调用频率控制。
import { useRateLimitedCallback } from '@tanstack/react-pacer'
// 每秒最多调用 5 次
const rateLimitedFetch = useRateLimitedCallback(
(url: string) => fetchData(url),
{ limit: 5, window: 1000 }
)
队列(Queuing):管理异步任务执行顺序。支持 FIFO/LIFO、优先级、暂停/恢复、取消、重试、并发控制。
import { AsyncQueuer } from '@tanstack/pacer'
// 最多同时上传 3 个文件
const uploadQueue = new AsyncQueuer(uploadFile, { concurrency: 3 })
uploadQueue.addItem(file1)
uploadQueue.addItem(file2)
uploadQueue.addItem(file3)
uploadQueue.addItem(file4) // 排队等前面的完成
// 暂停队列(不丢失排队中的任务)
uploadQueue.pause()
// 恢复
uploadQueue.resume()
批量处理(Batching):把多个操作合并成一次执行。适合日志上报、批量写入。
import { Batcher } from '@tanstack/pacer'
// 收集日志,每 5 秒或满 100 条时批量发送
const logBatcher = new Batcher(
(logs) => sendLogs(logs),
{ maxSize: 100, wait: 5000 }
)
logBatcher.addItem('用户点击了按钮')
logBatcher.addItem('用户打开了菜单')
// 这些日志会被批量发送,而不是一条条发
38.2.3 Pacer 的特点
- 同步和异步都支持:防抖节流既支持同步函数,也支持异步函数。异步版有额外的状态(pending、success、error)。
- 可观察的状态:每个工具都暴露状态(是否在等待、是否在执行、排队了多少个),可以绑到 UI 上显示。
- 手动控制:不只是被动等待,可以手动 flush(立即执行)、cancel(取消)、pause/resume(暂停恢复)。
- 框架适配器:核心逻辑框架无关,React/Solid/Vue/Angular 都有适配器。
TipPacer 和第 33 章讲的 Form 内置防抖不同。Form 的
onChangeAsyncDebounceMs只用于表单校验。Pacer 是通用的时间控制工具,任何场景都能用。
38.2.4 和 Form 校验防抖的对比
Form 里的防抖:
// Form 内置,只用于校验
<form.Field
validators={{
onChangeAsyncDebounceMs: 500,
onChangeAsync: async ({ value }) => { ... }
}}
>
Pacer 的防抖:
// 通用,任何回调都能防抖
const debouncedFn = useDebouncedCallback(fn, { wait: 500 })
两者不冲突。Form 校验用 Form 内置的,其他场景用 Pacer。
38.3 TanStack Ranger 简介
TanStack 还有个叫 Ranger 的小库,专门做范围滑块(Range Slider)。
WarningRanger 当前版本 v0.0.5,极早期。功能可能不完整,生产慎用。
import { useRanger } from '@tanstack/react-ranger'
function RangeSlider() {
const ranger = useRanger({
min: 0,
max: 100,
stepSize: 5,
values: [25, 75],
onChange: (values) => console.log(values),
})
// 用 ranger 提供的数据自己渲染滑块 UI
}
Ranger 也是 headless 的—只管滑块的数值计算和交互逻辑,UI 你自己画。适合需要自定义滑块样式的场景。但目前极早期,功能有限,教程里知道有这个东西就行。
38.4 TanStack 生态全景
38 章走下来,TanStack 生态的版图已经清晰了:
| 库 | 定位 | 成熟度 | 章节 |
|---|---|---|---|
| Query | 服务端状态管理 | 稳定 v5 | 4-14 |
| Router | 类型安全路由 | 稳定 v1 | 15-21 |
| Start | 全栈框架 | v1 RC | 22-25 |
| Table | headless 表格 | 稳定 v8 | 26-31 |
| Form | headless 表单 | 稳定 v1 | 32-34 |
| Virtual | 虚拟化列表 | 稳定 v3 | 35-36 |
| Store | 响应式状态管理 | v0.11 | 37 |
| DB | 客户端数据库 | v0 早期 | 38 |
| Pacer | 时间控制工具 | v0 | 38 |
| Ranger | 范围滑块 | v0.0.5 极早期 | 38 |
三个核心理念贯穿整个生态:
- headless(无头):Table、Form、Virtual、Ranger 都是只管逻辑不管 UI。你完全掌控样式。
- 框架无关(Framework-agnostic):核心逻辑不依赖任何框架,React/Vue/Solid/Svelte/Angular 都有适配器。
- 类型安全(Type-safe):从 Router 的路由参数到 Table 的列定义,从 Form 的字段值到 Store 的状态,全链路 TypeScript 类型推导。
38.5 选型建议
面对这么多库,怎么选?
服务端数据:TanStack Query 是必选。几乎所有 React 项目都受益。
路由:新项目、用 TypeScript、重视类型安全,选 TanStack Router。老项目已经在 React Router 上跑着,没强需求不用换。
全栈:要 SSR、Server Functions、全栈一体化,用 TanStack Start(内置 Router)。
表格:需要高度定制、轻量、免费,用 TanStack Table。要开箱即用、功能全(Excel 导出、透视表),用 ag-Grid。
表单:字段多、校验复杂、要类型安全,用 TanStack Form。简单表单 useState 就行。
长列表:数据量上千、滚动卡顿,用 TanStack Virtual。
全局状态:轻量需求用 TanStack Store。复杂状态管理 Redux/Zustand 也行。
客户端数据库:数据量大、关联复杂、需要实时更新,关注 TanStack DB(还在 v0)。
时间控制:防抖节流限流队列,用 TanStack Pacer(还在 v0,也可用 lodash.debounce 等替代)。
38.6 生态展望
TanStack 生态还在快速演进:
- DB 和 Pacer 正在从 v0 走向稳定,一旦 1.0 发布,整个生态的客户端数据层和时间控制能力会大幅提升。
- Table v9 已在 beta 中,API 有调整(
useReactTable->useTable+tableFeatures),但 v8 仍是当前稳定版。 - Store 的 atom 机制在持续完善,未来可能成为整个生态统一的响应式原语。
- Start 在全栈方向上持续迭代,SSR、部署、DX 都在改善。
TanStack 的理念一直没变:headless、框架无关、类型安全。这套理念让它的库既有底层控制力,又能跨框架复用。学一套理念,受益多个库。
Note技术选型没有银弹。TanStack 的库在类型安全和灵活性上很强,但学习曲线比「开箱即用」的库陡。根据项目需求权衡,别为了用而用。
38.7 小结
这是整个教程的最后一章。你了解了:
- TanStack DB:客户端数据库,用集合(Collections)存数据、实时查询(Live Queries)做关联过滤、乐观变更做自动回滚。底层用差分数据流实现毫秒级增量更新。
- TanStack Pacer:时间控制工具箱,防抖、节流、限流、队列、批量处理五大能力。同步异步都支持,状态可观察,可手动控制。
- TanStack Ranger:范围滑块库,极早期,知道有就行。
- 生态全景:10 个库,三大理念(headless、框架无关、类型安全),从数据获取到路由到全栈到表格表单到虚拟化到状态管理,覆盖前端开发方方面面。
38 章的旅程到此结束。从 Query 的第一个 useQuery 开始,到 DB 的差分数据流结束,你走完了 TanStack 生态的完整版图。剩下的就是在项目里实践、踩坑、成长。祝你好运。