一个库到一整个宇宙
兄弟们,你们还记得 TanStack 最开始的样子吗?
那时候它还叫 React Query,一个帮你在 React 里管理服务端状态的小库。功能单一但有特色——让数据 fetching 变得优雅。
几年过去了,Tanner Linsley 像开了挂一样,把 TanStack 从一个库扩展成了一整个前端工具生态系统。2026 年的 TanStack 已经不是”那个做表格的库”了,它是一整套模块化、可组合、类型安全的前端基础设施。从数据获取到路由,从表单到表格,从状态管理到 AI 集成,它覆盖了前端开发的每一个维度。
TanStack 全家桶一览
先来看一张全景图:
| 库名 | 用途 | GitHub Stars | 2026 年新变化 |
|---|---|---|---|
| TanStack Query | 服务端状态管理 | 45K+ | V6 支持 Streaming 响应 |
| TanStack Table | 数据表格 | 27K+ | V9 内置虚拟化引擎 |
| TanStack Router | 路由 | 12K+ | V2 支持 RSC |
| TanStack Form | 表单 | 8K+ | 2025 年新成员,持续迭代 |
| TanStack Store | 状态管理 | 5K+ | 轻量级 Zustand 替代品 |
| TanStack Start | 全栈框架 | 15K+ | Next.js 的强力竞争者 |
| TanStack AI | AI 集成 | 6K+ | 2026 年最受关注的新项目 |
| TanStack DB | 数据库客户端 | 4K+ | 类型安全的 SQL 构建器 |
这个生态的覆盖面已经非常惊人了。从你打开浏览器输入 URL 开始,到数据加载、路由解析、表单交互、表格展示,甚至到后端的数据库查询,TanStack 全包了。
TanStack Query V6:Streaming 时代的查询库
2026 年最有意思的变化是 TanStack Query V6 加入了对 Streaming 的原生支持。以前要实现流式更新,你得自己管理 WebSocket 或者 EventSource,再配合各种状态管理。现在一个 useQuery 搞定。
import { useQuery } from '@tanstack/react-query';
// V6 的新特性:流式响应function ChatStream() { const query = useQuery({ queryKey: ['chat', conversationId], queryFn: async ({ signal }) => { const response = await fetch('/api/chat/stream', { signal }); const reader = response.body!.getReader(); const decoder = new TextDecoder();
let content = ''; while (true) { const { done, value } = await reader.read(); if (done) break; content += decoder.decode(value, { stream: true }); } return content; }, streaming: true, // V6 新增:流式更新 UI });
return <div>{query.data}</div>;}除了 Streaming,V6 还改进了缓存 GC 策略和 optimistic update 的 API。现在乐观更新的代码写得比之前简洁多了:
const mutation = useMutation({ mutationFn: updateTodo, onMutate: async (newTodo) => { // 立即取消正在进行的查询 await queryClient.cancelQueries({ queryKey: ['todos'] }); // 保存快照用于回滚 const previous = queryClient.getQueryData(['todos']); // 乐观更新 queryClient.setQueryData(['todos'], old => [...old, newTodo]); return { previous }; }, onError: (err, newTodo, context) => { // 出错时回滚 queryClient.setQueryData(['todos'], context?.previous); },});TanStack Router V2:路由的终极形态
TanStack Router V2 最大的亮点是 对 React Server Components 的完整支持。它采用了文件系统路由 + 类型安全的 loader 设计,每个路由可以独立定义数据加载逻辑。
import { createRouter, Route } from '@tanstack/react-router';
const indexRoute = new Route({ getParentRoute: () => rootRoute, path: '/', component: HomePage,});
const postsRoute = new Route({ getParentRoute: () => rootRoute, path: 'posts', loader: async ({ context: { db } }) => { return db.post.findMany({ orderBy: { publishedAt: 'desc' }, take: 20, }); }, component: ({ useLoaderData }) => { const posts = useLoaderData(); // 自动推断类型 return ( <div> {posts.map(post => ( <PostCard key={post.id} post={post} /> ))} </div> ); },});
const router = createRouter({ routeTree: rootRoute.addChildren([indexRoute, postsRoute]),});TypeScript 的类型推导做得非常出色——loader 返回什么类型,component 里就能自动推断出什么类型,不需要手动标注。这意味着你改了数据库查询的返回字段,前端的 TypeScript 会立刻告诉你哪里需要调整。
TanStack Start:全栈框架的新势力
TanStack Start 是 2026 年最让我兴奋的新项目之一。它是一个基于 TanStack Router 的全栈框架,有点像 Next.js 但更加”无侵入”。
# 创建新项目npm create tanstack-app@latest my-app -- --template react
# 目录结构my-app/├── app/│ ├── routes/│ │ ├── __root.tsx│ │ ├── index.tsx│ │ └── posts.$id.tsx│ ├── components/│ ├── server/│ │ └── db.ts│ └── client.tsx├── tanstack.config.ts└── package.json// app/server/db.ts - 仅在服务器端运行import { createDatabase } from '@tanstack/db';
export const db = createDatabase({ url: process.env.DATABASE_URL!,});
// app/routes/posts.$id.tsx - 自动类型推导import { Route } from '@tanstack/react-router';import { db } from '../server/db';
export const route = new Route({ path: 'posts/$id', loader: async ({ params: { id } }) => { return db.post.findUnique({ where: { id }, include: { author: true, comments: true }, }); }, component: ({ useLoaderData }) => { const post = useLoaderData(); return <Article post={post} />; },});最关键的是:TanStack Start 不做任何”魔法”。它不黑掉你的 Vite 配置,不偷偷往你的页面 inject 脚本,不搞独有格式。它只是一个在标准 Vite + React 之上搭建的框架。
TanStack AI:让 AI 集成像 Query 一样简单
2026 年 TanStack 家族的最新成员是 TanStack AI,一个让前端开发者轻松对接各种 AI 模型的工具库。
import { useAI } from '@tanstack/react-ai';
function AIChat() { const ai = useAI({ provider: 'openai', // 也支持 claude, gemini, 本地模型 model: 'gpt-4o', });
const { messages, sendMessage, isLoading } = ai.useChat({ systemPrompt: '你是一个友好的前端开发助手', maxContextLength: 4000, });
return ( <div> {messages.map(msg => ( <Message key={msg.id} role={msg.role} content={msg.content} /> ))} <Input onSubmit={(text) => sendMessage(text)} disabled={isLoading} /> </div> );}为什么这很重要?因为它在前端层面统一了 AI 调用的接口。不管用的是 OpenAI、Claude 还是本地跑的开源模型,API 接口是一样的。切换提供商只需要改一行 provider 配置。
TanStack Table V9:虚拟化内置
表格一直是 TanStack 的拳头产品。V9 版本最大的变化是内置了虚拟化引擎,以前你需要手动拼 @tanstack/react-virtual,现在一行配置搞定:
import { useReactTable, getCoreRowModel } from '@tanstack/react-table';
function LargeTable({ data, columns }) { const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), virtualize: true, // 自动虚拟化 virtualOptions: { estimateSize: 48, // 行高估计 overscan: 20, // 预渲染行数 }, });
return ( <table> <thead>{/* ... */}</thead> <tbody> {table.getRowModel().rows.map(row => ( <tr key={row.id}> {row.getVisibleCells().map(cell => ( <td key={cell.id}> {flexRender(cell.column.columnDef.cell, cell.getContext())} </td> ))} </tr> ))} </tbody> </table> );}100 万行数据打开瞬间渲染,滚动丝滑流畅。这在 V9 之前需要自己折腾 react-window 或者 react-virtuoso。
写在最后
从 React Query 到 TanStack 全家桶,Tanner Linsley 用几年时间证明了一件事:最好的库不是为了解决某个问题而生的,而是为了改变你思考问题的方式。
2026 年的 TanStack 已经不仅仅是”瑞士军刀”了,它正在成为一个完整的全栈开发范式。从数据获取到路由,从表单到表格,从状态管理到 AI 集成,它覆盖了前端开发的每一个维度。如果你还没试过 TanStack Start 或者 TanStack AI,我强烈建议你花一个下午的时间跑个 demo。相信我,你会被它的开发体验惊艳到。
为什么选择 TanStack 而不是其他方案
你可能会有疑问,现在全栈框架这么多,Next.js、Remix、Nuxt 都有各自的生态,为什么还要关注 TanStack?我的理由是:TanStack 是唯一一个完全模块化的全栈生态。你不必为了用 Query 就得上 Router,也不必为了用 Table 就得上 Start。你需要什么就装什么,其他部分完全可以继续用你熟悉的工具。这种渐进式采用的体验在 2026 年的前端世界里越来越受欢迎。相比之下,Next.js 是一个”全有或全无”的方案,你一旦用了 App Router,基本上就得按照它的方式来组织代码。当然 Next.js 本身也很优秀,只是不同的选择适合不同的团队。
TanStack Form 的独特设计
TanStack Form 是 2025 年新加入家族的产品,经过一年多的迭代已经非常成熟了。它跟其他表单库最大的不同是它的类型安全设计。以前写表单最痛苦的事情是什么?是表单字段的类型和提交数据的类型不一致。TanStack Form 利用 TypeScript 的类型推导能力,让你定义好表单结构之后,values、errors、touched 这些状态自动拥有正确的类型。如果你改了字段名,TypeScript 会告诉你要改哪些地方,而不是等你运行时才发现字段 undefined。这种体验用过就回不去了。
实际项目中的使用建议
如果你打算在一个新项目中尝试 TanStack 生态,我的建议是从 Query 和 Router 开始。这两个是 TanStack 最成熟的产品,社区资源也最多。等你对这两个库的 API 风格熟悉了之后,再逐步引入 Form 和 Table。最后再考虑要不要用 Start 替代现有的全栈框架。渐进式采用的好处是每一步的风险都很小,即使某个库不适合你,切换的成本也很低。我们用了一年多 TanStack 生态,从 Query 开始,到 Router,再到 Form,目前正在评估 Start。整个过程非常平滑,没有遇到什么大的坑。
TanStack Query 的缓存策略
谈了这么多 TanStack 家族的成员,最后深入聊一下 Query 的缓存策略,因为这是它最核心也最容易被误解的部分。Query 的缓存不是简单的”请求一次就缓存起来”那么简单。它有一套复杂的缓存生命周期管理:当你的组件挂载时,如果缓存数据存在并且没有过期,直接使用缓存;如果数据过期了但还没有被清除,先展示旧数据然后在后台重新获取新数据;如果缓存被清除或者不存在,显示加载状态。这套策略叫做 stale-while-revalidate,它保证了用户永远能看到数据(即使是旧数据),同时又能在后台保持数据的新鲜度。默认情况下,缓存数据在 30 秒后变为 stale(过时),但会继续留在内存中 5 分钟。你完全可以根据业务需求调整这些参数。比如对于用户资料这种不经常变化的数据,可以把 staleTime 设成 5 分钟;对于股票价格这种实时性要求高的数据,可以把 staleTime 设成 0。