与其他工具比较
RTK Query 从生态系统中的许多其他数据获取库中汲取灵感。就像 Redux 核心库受到 Flux 和 Elm 等工具的启发 一样,RTK Query 建立在 React Query、SWR、Apollo 和 Urql 等库普及的 API 设计模式和功能概念之上。RTK Query 是从头开始编写的,但试图利用这些库和其他数据获取工具的最佳概念,并着眼于利用 Redux 的独特优势和功能。
我们认为所有这些工具都很棒!如果您正在使用其中一个工具,并且您对它感到满意,并且它解决了您在应用程序中遇到的问题,请继续使用该工具。本页面的信息旨在帮助说明在功能、实现方法和 API 设计方面存在哪些差异。目标是帮助您做出明智的决策并了解权衡,而不是争论工具 X 比工具 Y 更好。
何时应该使用 RTK Query?
一般来说,使用 RTK Query 的主要原因是
- 您已经有一个 Redux 应用程序,并且想要简化现有的数据获取逻辑
- 您希望能够使用 Redux DevTools 查看状态随时间变化的历史记录
- 您希望能够将 RTK Query 行为与 Redux 生态系统的其他部分集成
- 您的应用程序逻辑需要在 React 之外工作
独特功能
RTK Query 有一些独特的 API 设计方面和功能值得考虑。
- 使用 React Query 和 SWR,您通常会自己定义钩子,并且可以在任何地方和任何时候进行定义。使用 RTK Query,您可以在一个中心位置通过提前定义具有多个端点的“API 切片”来做到这一点。这允许更紧密集成的模型,其中突变会自动使查询失效/重新获取触发器。
- 由于 RTK Query 在处理请求时会分派正常的 Redux 操作,因此所有操作都可以在 Redux DevTools 中看到。此外,每个请求都会自动对您的 Redux 减少器可见,并且可以轻松地更新全局应用程序状态,如果需要(查看示例)。您可以使用端点 匹配器功能 在您自己的减少器中对与缓存相关的操作进行额外的处理。
- 与 Redux 本身一样,主要的 RTK Query 功能与 UI 无关,可以与任何 UI 层一起使用
- 您可以轻松地从中间件使实体失效或修补现有查询数据(通过
util.updateQueryData
)。 - RTK Query 启用 流式缓存更新,例如在通过 websocket 接收消息时更新最初获取的数据,并且内置支持 乐观更新。
- RTK Query 附带了一个非常小巧灵活的 fetch 包装器:
fetchBaseQuery
。也很容易 用您自己的客户端替换我们的客户端,例如使用axios
、redaxios
或自定义客户端。 - RTK Query 有一个 (目前处于实验阶段)代码生成工具,它将接受 OpenAPI 规范或 GraphQL 模式并为您提供一个类型化的 API 客户端,以及提供在事后增强生成的客户端的方法。
权衡
没有规范化或去重缓存
RTK Query 故意不实现会对来自多个请求的相同项进行去重的缓存。这有几个原因
- 一个完全规范化的跨查询共享缓存是一个很难解决的问题
- 我们现在没有时间、资源或兴趣去尝试解决这个问题
- 在许多情况下,当数据失效时简单地重新获取数据效果很好,而且更容易理解
- 至少,RTKQ 可以帮助解决“获取一些数据”的通用用例,这对很多人来说是一个很大的痛点
包大小
RTK Query 会为您的应用程序包大小添加一个固定的单次数量。由于 RTK Query 基于 Redux Toolkit 和 React-Redux,因此添加的大小会根据您是否已经在应用程序中使用它们而有所不同。估计的最小+gzip 包大小为
- 如果您已经使用 RTK:RTK Query 约 9kb,钩子约 2kb。
- 如果您还没有使用 RTK
- 没有 React:RTK+依赖项+RTK Query 17 kB
- 使用 React:19kB + React-Redux,这是一个对等依赖项
添加额外的端点定义应该只会根据endpoints
定义中的实际代码增加大小,这通常只有几个字节。
RTK Query 中包含的功能很快就能弥补添加的包大小,并且消除手动编写的获取数据逻辑对于大多数有意义的应用程序来说应该是包大小的净改进。
比较功能集
值得比较所有这些工具的功能集,以了解它们的异同。
此比较表力求尽可能准确和公正。如果您使用任何这些库并认为信息可以改进,请随时通过打开一个问题提出更改建议(附带说明或证据)。
功能 | rtk-query | react-query | apollo | urql |
---|---|---|---|---|
支持的协议 | 任何,包括 REST | 任何,不包括任何 | GraphQL | GraphQL |
API 定义 | 声明式 | 使用时,声明式 | GraphQL 模式 | GraphQL 模式 |
按以下方式缓存 | 端点 + 序列化参数 | 用户定义的查询键 | 类型/ID | 类型/ID? |
失效策略 + 重新获取 | 声明式,按类型和/或类型/ID | 按缓存键手动 | 每个实体级别的自动缓存更新,按缓存键手动查询失效 | 声明式,按类型或每个实体级别的自动缓存更新,按缓存键手动查询失效 |
轮询 | 是 | 是 | 是 | 是 |
并行查询 | 是 | 是 | 是 | 是 |
依赖查询 | 是 | 是 | 是 | 是 |
跳过查询 | 是 | 是 | 是 | 是 |
延迟查询 | 是 | 是 | 否 | ? |
自动垃圾回收 | 是 | 是 | 否 | ? |
规范化缓存 | 否 | 否 | 是 | 是 |
无限滚动 | 待办事项 | 是 | 需要手动代码 | ? |
预取 | 是 | 是 | 是 | 是? |
重试 | 是 | 是 | 需要手动代码 | ? |
乐观更新 | 可以手动更新缓存 | 可以手动更新缓存 | optimisticResponse | ? |
手动缓存操作 | 是 | 是 | 是 | 是 |
平台 | React 的钩子,Redux 可用的任何地方 | React 的钩子 | 各种 | 各种 |
更多信息
- React Query 的“比较”页面包含一个额外的详细功能集比较表和功能讨论
- Urql 维护者 Phil Pluckthun 撰写了一篇关于“规范化缓存”是什么以及 Urql 缓存如何工作的优秀解释
- RTK Query 的“缓存行为”页面包含有关 RTK Query 为什么不实现规范化缓存的更多详细信息