• AaronConlon.dev
  • Talk
  • Weekly
  • 工具
  • 编程
  • 翻译
  • 资讯
  • 通识

TanStack 的崛起(上):从 React Query 到前端应用栈

2026年07月20上次更新于 大约 2 个月前
编程

hello!大家好!今天,我给大家分享一个我超级喜欢的技术栈的故事:TanStack!

前端工具的竞争,表面上是 API 的竞争,底层其实是对复杂度的重新分配:哪些事情交给框架,哪些事情交给应用,哪些事情应该由类型系统提前约束。

一个库能不能长期留下来,往往不只取决于它能不能解决一个问题,也取决于它能不能在下一个问题出现时继续保持同一套判断。

今天,让我们一起来了解一下 TanStack 的技术“史诗”!

它最初因为 React Query 被更多开发者认识,后来逐步扩展到路由、全栈框架、表格、表单、虚拟列表、AI 与开发工具。今天的 TanStack 已经不太像一组彼此独立的工具,而更像一套围绕 TypeScript、数据流和应用边界组织起来的前端应用栈。

让我们沿着产品技术栈一步步向前走:React Query 解决了什么,TanStack 为什么要改名,竞品各自把复杂度放在哪里,以及这些公开 Issue 如何暴露出它的优势与代价。

React Query 先解决了什么

在 React Query 出现之前,前端获取数据通常会混合几种工作:组件启动请求、显示 loading、处理错误、保存结果、判断结果是否过期、响应窗口重新聚焦、处理重复请求,以及在修改数据后让相关页面重新获取数据。

这些工作并不难单独完成,难的是它们会在每个页面重复出现。一个页面写一套 useEffect,另一个页面写一套全局状态,最后大家都要回答同样的问题:这份数据现在属于谁?多久算旧?两个组件同时请求同一个资源时,能不能复用结果?修改完成后,哪些缓存需要失效?

这些问题贯穿着 React 项目的方方面面,无论开发者水平是高是低,都需要直接面对这个问题。在一个团队里,给出一份稳定、高效且让大家都满意的方案并不简单。

React Query 的重要变化,是把问题从“如何在组件里发请求”改成“如何声明一份服务器状态”。在今天的 TanStack Query 里,查询键、查询函数和缓存生命周期组成了一个相对完整的模型。

最小的使用方式看起来很简单:


const todosQuery = useQuery({

  queryKey: ['todos'],

  queryFn: fetchTodos,

})

少写几行请求代码价值并不大,这几个概念被固定了下来才是重头戏:

  • queryKey 是缓存的身份,也是依赖关系的声明;

  • 查询结果可以在组件之间共享,并自动去重;

  • 新数据可以在后台刷新,页面不必每次都回到空白 loading;

  • mutation 可以和失效、乐观更新、回滚联系起来;

  • 缓存、重试、离线和开发调试都有统一入口。

以上功能涉及到了 Web 开发的方方面面,每一个都可以单独拉出来开发一个 npm 包,但是 Tanstack Query 直接给我们提供了一个完整的、强类型的无敌解决方案!

这让“服务器状态”和“客户端状态”开始分开。输入框是否展开、弹窗是否打开,仍然适合交给组件状态或状态管理库;来自接口、会过期、可能被别的用户修改的数据,则应该有自己的缓存和同步机制。

小黑整理服务器状态

React Query 最早的影响,正是让很多团队意识到:不是所有状态都应该塞进 Redux,也不是所有异步逻辑都应该散落在副作用里。

从 React Query 到 TanStack Query

2022 年发布的 v4 是一次关键转折。官方在 v4 发布文章 中说明,项目从过去的 React 专属库,重构为无框架核心加框架适配器的形式,并开始支持 Vue、Svelte 和 Solid。

这次改名不是简单换一个 npm 包名。它改变了项目的边界:核心缓存、查询客户端、订阅和状态转换尽量不依赖具体 UI 框架;React 的 hook、Vue 的组合式接口,属于上层适配器。这样做有两个直接收益。

第一,维护者可以复用同一套数据逻辑。第二,用户学到的不是某个框架的技巧,而是一套可以迁移的服务器状态模型。v4 还加入了更完整的离线支持、持久化和 React 18 兼容能力,说明它已经不满足于“帮你发请求”,而是在争取成为异步状态的基础设施。

到了 v5,项目继续收紧 API,拥抱更现代的 TypeScript 和 React 并发模型。这种演进方式也埋下了 TanStack 的一个特征:它愿意为了长期模型调整短期兼容性,但会把迁移说明、类型边界和取舍放到台面上讨论,团队开发人员在 github 上发布了大量解释性回复,同时也写了很多实用的教程和博客。

小黑把 React Query 挂上跨框架桥

按产品技术栈看 TanStack

TanStack 产品矩阵

上图是 TanStack 当前产品矩阵的一个概览。它的扩张不是简单地“看到什么热门就做什么”,大致可以按五层来理解。

框架层:Router 与 Start

TanStack Router 是这套体系的路由基础。它把路由树、路径参数、搜索参数、loader、预加载和 pending 状态纳入类型系统。尤其是搜索参数,它不再只是一个字符串,而可以有明确的结构、解析和序列化规则。

这种设计很适合数据密集型应用:列表筛选、分页、排序和详情页状态都能映射到 URL,loader 又可以和查询缓存配合。路由因此不只是页面切换工具,而变成了应用数据流的一部分。

小黑校准 Router 与 Start 的边界

这种设计真的非常 nice,我们不用再去花时间精力找各种不同的解决方案。

TanStack Start 则在 Router 之上继续向全栈靠近。它提供服务端渲染、流式输出、服务端函数、服务端路由和面向不同运行时的构建结果。官方目前仍标记为 RC,这个状态很重要:它代表产品方向已经清楚,但基础设施仍处于快速打磨阶段。

数据与状态层:Query、DB、Store 与 AI

Query 是最成熟、最容易理解的一层:它负责远程数据的缓存、同步和更新。

DB 试图把客户端数据存储做得更具反应性,让接口数据可以在本地形成可查询、可订阅的关系。Store 更靠近一般客户端状态,但仍然延续轻量、类型友好的思路。AI 则把流式文本、工具调用、多模态和 agent 场景纳入同一套 TypeScript 接口。

官网当前将 DB 标为 beta、AI 标为 beta、Store 标为 alpha。把这些状态公开标出,既是风险提示,也是一种产品管理方式:用户可以清楚知道 Query、Router 这样的成熟工具,与新工具之间并不处在同一个稳定等级。

UI 与体验层:Table、Form 与 Hotkeys

TanStack Table 的定位很典型:它是 headless 的表格引擎,不替你决定 HTML、CSS 和组件外观。排序、筛选、分组、分页、行选择等能力由它提供,最终如何渲染由应用自己决定。

这条路线和“开箱即用”的表格组件不同。它牺牲了一部分上手速度,换来设计自由、组件库兼容性和更细的性能控制。Form 与 Hotkeys 也延续同样思路:提供状态和行为模型,不强迫应用接受一套视觉语言。

性能层:Virtual 与 Pacer

Virtual 负责大列表、大表格的窗口化渲染,让应用只渲染视口附近的数据。它和 Table 的组合很自然:Table 管理数据模型,Virtual 管理可见范围。

Pacer 更像是性能调度工具,用来处理节流、防抖、批处理和高频更新。它们共同说明 TanStack 的关注点正在从“有没有功能”转向“功能在复杂数据量和高频交互下是否还能保持可控”。

小黑拧紧可组合的产品栈

工具层:Devtools、Config、CLI 与 Intent

Devtools 负责观察查询、路由和缓存;Config、CLI 和 Intent 则在把工程配置、项目初始化与 AI agent 的工作方式纳入产品范围。尤其是 Intent 这类工具,反映出维护者开始考虑一个新问题:未来不只有人会阅读文档和修改代码,agent 也需要可靠地发现、安装和使用这些能力。

上篇先写到这里

从 React Query 到产品矩阵,TanStack 的第一步是把服务器状态、路由、全栈边界和数据视图逐渐放进一套可组合的技术栈。下篇将继续从竞品和公开 Issue 出发,看看这些选择在真实工程里意味着什么。


not-by-ainot-by-ai
已读 0%
文章推荐
文章封面
GitHub 故障 7 小时复盘:最隐蔽的重试风暴
更新于 2026-08-20
编程
文章封面
Sass 浅解
更新于 2024-08-08
编程
GitHubTwitter / XMediumDevJuejin

友情链接

Jimmy
Jimmy
老胡
老胡
Submara
Submara
Bruce Song
Bruce Song
Scarsu
Scarsu
宇阳
宇阳
Steven Lynn's Blog
Steven Lynn's Blog
OJ·Jimmy (Other Jimmy)
OJ·Jimmy (Other Jimmy)
liruifengv - Web 开发者,Astro 项目成员,开源爱好者。
liruifengv - Web 开发者,Astro 项目成员,开源爱好者。