此比较表力求尽可能准确和公正。如果您使用这些库中的任何一个,并觉得信息可以改进,请随时使用本页面底部的“在 Github 上编辑此页面”链接提出更改建议(附注或证据)。
特性/功能键
React Query | SWR (网站) | Apollo Client (网站) | RTK-Query (网站) | React Router (网站) | |
---|---|---|---|---|---|
Github 仓库 / 星星数 | |||||
平台要求 | React | React | React, GraphQL | Redux | React |
他们的比较 | (无) | (无) | 比较 | (无) | |
支持的查询语法 | Promise, REST, GraphQL | Promise, REST, GraphQL | GraphQL, 任何(响应式变量) | Promise, REST, GraphQL | Promise, REST, GraphQL |
支持的框架 | React | React | React + 其他 | 任何 | React |
缓存策略 | 分层键 -> 值 | 唯一键 -> 值 | 规范化 Schema | 唯一键 -> 值 | 嵌套路由 -> 值 |
缓存键策略 | JSON | JSON | GraphQL Query | JSON | 路由路径 |
缓存更改检测 | 深度比较键(稳定序列化) | 深度比较键(稳定序列化) | 深度比较键(不稳定序列化) | 键引用相等(===) | 路由更改 |
数据更改检测 | 深度比较 + 结构共享 | 深度比较(通过 stable-hash) | 深度比较(不稳定序列化) | 键引用相等(===) | Loader 运行 |
数据记忆化 | 完全结构共享 | 标识(===) | 规范化标识 | 标识(===) | 标识(===) |
打包大小 | |||||
API 定义位置 | 组件,外部配置 | 组件 | GraphQL Schema | 外部配置 | 路由树配置 |
查询 | ✅ | ✅ | ✅ | ✅ | ✅ |
缓存持久化 | ✅ | ✅ | ✅ | ✅ | 🛑 仅活动路由 8 |
开发工具 | ✅ | ✅ | ✅ | ✅ | 🛑 |
轮询/间隔 | ✅ | ✅ | ✅ | ✅ | 🛑 |
并行查询 | ✅ | ✅ | ✅ | ✅ | ✅ |
依赖查询 | ✅ | ✅ | ✅ | ✅ | ✅ |
分页查询 | ✅ | ✅ | ✅ | ✅ | ✅ |
无限查询 | ✅ | ✅ | ✅ | ✅ | 🛑 |
双向无限查询 | ✅ | 🔶 | 🔶 | ✅ | 🛑 |
无限查询重新获取 | ✅ | ✅ | 🛑 | ✅ | 🛑 |
滞后查询数据1 | ✅ | ✅ | ✅ | ✅ | ✅ |
选择器 | ✅ | 🛑 | ✅ | ✅ | 不适用 |
初始数据 | ✅ | ✅ | ✅ | ✅ | ✅ |
滚动恢复 | ✅ | ✅ | ✅ | ✅ | ✅ |
缓存操作 | ✅ | ✅ | ✅ | ✅ | 🛑 |
废弃查询清除 | ✅ | ✅ | ✅ | ✅ | ✅ |
渲染批处理和优化2 | ✅ | ✅ | 🛑 | ✅ | ✅ |
自动垃圾回收 | ✅ | 🛑 | 🛑 | ✅ | 不适用 |
Mutation Hooks | ✅ | ✅ | ✅ | ✅ | ✅ |
离线 Mutation 支持 | ✅ | 🛑 | 🟡 | 🛑 | 🛑 |
预取 API | ✅ | ✅ | ✅ | ✅ | ✅ |
查询取消 | ✅ | 🛑 | 🛑 | 🛑 | ✅ |
部分查询匹配3 | ✅ | 🔶 | ✅ | ✅ | 不适用 |
Stale While Revalidate(过时重新验证) | ✅ | ✅ | ✅ | ✅ | 🛑 |
Stale Time 配置 | ✅ | 🛑7 | 🛑 | ✅ | 🛑 |
预使用查询/Mutation 配置4 | ✅ | 🛑 | ✅ | ✅ | ✅ |
窗口焦点重新获取 | ✅ | ✅ | 🛑 | ✅ | 🛑 |
网络状态重新获取 | ✅ | ✅ | ✅ | ✅ | 🛑 |
通用缓存脱水/再水化 | ✅ | 🛑 | ✅ | ✅ | ✅ |
离线缓存 | ✅ | 🛑 | ✅ | 🔶 | 🛑 |
React Suspense | ✅ | ✅ | ✅ | 🛑 | ✅ |
抽象/无关核心 | ✅ | 🛑 | ✅ | ✅ | 🛑 |
Mutation 后自动重新获取5 | 🔶 | 🔶 | ✅ | ✅ | ✅ |
规范化缓存6 | 🛑 | 🛑 | ✅ | 🛑 | 🛑 |
1 滞后查询数据 - React Query 提供了一种在下一个查询加载时继续查看现有查询数据的方法(类似于 Suspense 即将原生提供的相同用户体验)。这在编写分页 UI 或无限加载 UI 时非常重要,因为您不希望在请求新查询时显示硬加载状态。其他库没有此功能,并在新查询加载时为新查询渲染硬加载状态(除非已预取)。
2 渲染优化 - React Query 具有出色的渲染性能。默认情况下,它会自动跟踪访问的字段,并且仅当其中一个字段发生更改时才重新渲染。如果您想选择退出此优化,将 notifyOnChangeProps 设置为 'all' 将在查询更新时重新渲染您的组件。例如,因为它有新数据,或者指示它正在获取。React Query 还将更新批处理在一起,以确保当多个组件使用相同的查询时,您的应用程序只重新渲染一次。如果您只对 data 或 error 属性感兴趣,您可以通过将 notifyOnChangeProps 设置为 ['data', 'error'] 来进一步减少渲染次数。
3 部分查询匹配 - 因为 React Query 使用确定性查询键序列化,这允许您操作可变查询组,而无需知道您想要匹配的每个单独的查询键,例如,您可以重新获取其键以 todos 开头的每个查询,无论变量如何,或者您可以使用(或不使用)变量或嵌套属性来定位特定查询,甚至可以使用筛选函数仅匹配通过您的特定条件的查询。
4 预使用查询配置 - 这只是一个花哨的名称,指能够在查询和 mutation 使用之前配置它们的行为方式。例如,查询可以预先完全配置默认值,当需要使用它时,只需 useQuery({ queryKey }),而无需在每次使用时传递 fetcher 和/或选项。SWR 具有此功能的部分形式,允许您预配置默认 fetcher,但仅作为全局 fetcher,而不是按查询基础,当然也不是用于 mutation。
5 Mutation 后自动重新获取 - 为了在 mutation 发生后实现真正的自动重新获取,需要一个 schema(例如 GraphQL 提供的 schema)以及有助于库知道如何在该 schema 中识别单个实体和实体类型的启发式方法。
6 规范化缓存 - React Query、SWR 和 RTK-Query 目前不支持自动规范化缓存,它描述了以扁平架构存储实体,以避免一些高级别的数据重复。
7 SWR 的不可变模式 - SWR 附带了一个“不可变”模式,它确实允许您在缓存的生命周期内只获取一次查询,但它仍然没有 stale-time 或条件自动重新验证的概念。
8 React Router 缓存持久化 - React Router 不会缓存超出当前匹配路由的数据。如果路由被离开,其数据将丢失。