提供fetch API 时,RTK 查询的实际需求是什么?

What's the actual need for RTK Query when fetch API is provided?

最初 Flux 的想法很明显。视图获取 Actions,然后根据更新商店的 Action 发出事件。但是,当我通读 redux-toolkit 时,似乎有多种方法可以实现一些微不足道的事情,即从端点获取 JSON 数据:

为什么完成最简单的任务有这么多不同的方法?

谢谢。

根据docs,该工具的目标是

It is designed to simplify common cases for loading data in a web application,
 eliminating the need to hand-write data fetching & caching logic yourself.

它提供了一些缓存,我个人觉得使用声明式 isLoading/error 非常方便,而无需每次都 useState :)

但同样,它只是可选的:RTK Query is an optional addon included in the Redux Toolkit package

确实有多种方法可以实现相同的目标。在 React 世界中,无论好坏,都没有黄金标准。

这个问题隐藏了很多sub-questions,所以我会根据我的经验尝试回答它们(我是RTK查询的部分粉丝).

  1. 要从浏览器通过 HTTP 请求资源,没有 多种 方法,您必须使用 xhrfetch API. xhr 是旧的 callback-based API, fetch 是现代的标准 promise-based API.
  2. 在这些 API 之上诞生了许多库来进行流程和配置 easier/wider,今天您将主要直接使用 fetch 或一些 gold-standard 像 axios 这样的库与 fetch 非常相似,但它有一些很酷的额外功能来处理获取调用和配置。
  3. 在像 React 这样的现代 frameworks/libraries 上,问题不是 如何通过 HTTP 检索资源,而是如何处理异步调用和响应的副作用创建到整个应用程序。
  4. 所以现在这打开了您登记的几个选项。

基本上对于非常基本的fetch调用,你可以在里面处理调用 一个 useEffect 如果它是一个必须检索数据以显示的 GET 调用 在刚刚自动安装的组件内部,或者 必须在单击按钮时开始获取,例如,如果它是 (通常)POST、PUT、ecc...调用。 然后,您可以将结果保存在 React 状态中,并进一步通过上下文将其传递到整个应用程序,让其他组件访问收到的响应。顺便说一下,这让您发现了许多其他行为,第一个是调用期间的加载状态,以及在错误状态响应或其他异常情况下的错误管理。顺便说一下,这肯定是您可以使用 useState 或更好的 useReducer 挂钩来简单实现的东西,所以这不是您会觉得需要一些异步调用管理器(如 RTK 查询)的真正原因。

重新生效

例如,如果您正在对 return 用户对象与用户数据进行登录时调用 post 调用,您将该数据保存在客户端状态管理器中(或 React state )并使用该状态在整个应用程序中显示用户数据。在您的应用程序的使用过程中,用户可以执行一些更改他在 DB 上的数据的操作,因此每次他这样做时您都必须小心,以重新获取他的数据并更新他的客户端数据对象,或者 return来自每个 POST/PUT/PATCH 等的新用户对象...调用并更新客户端状态,这很容易出错,因为如果您忘记在之后更新客户端状态,您可能会发现自己拥有未同步的 clientside/serverside 数据状态每个操作,或者在这些阶段是否存在问题。这通常会导致非常难以管理和调试的情况。 我想说这是开始使用像 RTK 查询这样的 Fetch 管理器First 很好的理由。 该管理器实现了一个非常简单的基于 Tags 的重新验证机制,让您可以为您执行的每个查询 ( GET ) 分配一个标签,例如,您将在用户登录时进行查询其中检索用户数据,您将使用 providesTags: 'User' 标记数据。 现在您可以安全地在后端对您的用户数据执行任意数量的突变,并且对于客户端的每个数据,您会告诉它一旦收到响应,它必须重新验证某个标签(或多个标签)。例如,您可能有一个 editPasswordMutation 来更改数据库中的用户密码,而您只需添加一个 invalidatesTags: 'User',这意味着一旦用户从服务器收到确认他已更新的肯定消息密码,客户端知道它必须重新执行 getUserData 调用,获取新的用户数据,并将它们保存到 redux 全局存储中,因此所有使用它们的应用程序组件都可以立即访问它们。 完全自动。 如果你自己实现的话,这整个机制肯定需要你写更多的代码。

乐观更新

大多数时候您会发现自己不希望 UI 在显示(例如)按钮点击的效果之前等待服务器响应。想象一下,当你在 Facebook 上点赞时,你会立即在你的 UI 中看到它,这并不是因为他们有超快的服务器,而是因为 UI 假设调用一旦你成功单击该按钮,它会立即为显示的 post 的喜欢计数添加 +1。 这种行为并非微不足道,因为通常当您在应用程序中显示数据时,您 应该 有一个单一的真实来源。因此,例如,如果您正在呈现博客列表 post,您应该从后端数据库中检索它们,将它们保存在客户端状态管理器中或直接呈现它们 as-is。如果第一个 post 有,假设有 10 个赞,您将根据 data.posts[0].likes.count 渲染它们。所以这就是你的真相来源。如果你想添加一个 Like/Dislike 按钮,并且你想实现一个乐观的更新,你将不得不手动改变它真相的来源,这一点都不好,因为它可以在多个组件之间共享(在全局状态的情况下)或复制它,并更改副本,但这也不好。 复制真实来源几乎从来都不是(几乎)一个好主意。 RTK 查询来拯救! 使用 RTK 查询 Optimistic Update 设置起来非常简单,基本上每次提取都可以实现乐观更新行为,因为您可以使用 life-cycle 方法 onQUeryStarted 来拦截立即开始通话,然后使用实用程序:updateQueryData 更新您的突变将要失效的数据。极其聪明。 所以在这种情况下,您将只有一个简单的突变,它会向博客 post 添加一个赞,该突变将使 posts 数据无效,单个 post 将立即在UI 与 +1 一样,同时服务器将重新获取 posts 列表(因为它们已失效)并同步检索新数据,用户会注意到非常流畅的体验。

还有许多其他功能,尤其是涉及 Cache 管理,这是一个加分项,(即使有时它们会产生一些问题)但我仅强调这两个主要功能促使我成为 RTK Query 的用户,开始时它可能看起来有点冗长,但它确实使事情变得非常干净整洁,与 Redux 哲学一致。