提供fetch API 时,RTK 查询的实际需求是什么?
What's the actual need for RTK Query when fetch API is provided?
最初 Flux
的想法很明显。视图获取 Actions
,然后根据更新商店的 Action
发出事件。但是,当我通读 redux-toolkit
时,似乎有多种方法可以实现一些微不足道的事情,即从端点获取 JSON 数据:
- 使用提取 API 从端点获取一些数据
- 使用 RTK 查询做同样的事情
- 使用 React 上下文 API
- 使用
useEffect()
挂钩
为什么完成最简单的任务有这么多不同的方法?
谢谢。
根据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查询的部分粉丝).
- 要从浏览器通过 HTTP 请求资源,没有 多种 方法,您必须使用
xhr
或 fetch
API.
xhr
是旧的 callback-based API, fetch
是现代的标准 promise-based API.
- 在这些 API 之上诞生了许多库来进行流程和配置 easier/wider,今天您将主要直接使用
fetch
或一些 gold-standard 像 axios
这样的库与 fetch
非常相似,但它有一些很酷的额外功能来处理获取调用和配置。
- 在像 React 这样的现代 frameworks/libraries 上,问题不是 如何通过 HTTP 检索资源,而是如何处理异步调用和响应的副作用创建到整个应用程序。
- 所以现在这打开了您登记的几个选项。
基本上对于非常基本的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 哲学一致。
最初 Flux
的想法很明显。视图获取 Actions
,然后根据更新商店的 Action
发出事件。但是,当我通读 redux-toolkit
时,似乎有多种方法可以实现一些微不足道的事情,即从端点获取 JSON 数据:
- 使用提取 API 从端点获取一些数据
- 使用 RTK 查询做同样的事情
- 使用 React 上下文 API
- 使用
useEffect()
挂钩
为什么完成最简单的任务有这么多不同的方法?
谢谢。
根据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查询的部分粉丝).
- 要从浏览器通过 HTTP 请求资源,没有 多种 方法,您必须使用
xhr
或fetch
API.xhr
是旧的 callback-based API,fetch
是现代的标准 promise-based API. - 在这些 API 之上诞生了许多库来进行流程和配置 easier/wider,今天您将主要直接使用
fetch
或一些 gold-standard 像axios
这样的库与fetch
非常相似,但它有一些很酷的额外功能来处理获取调用和配置。 - 在像 React 这样的现代 frameworks/libraries 上,问题不是 如何通过 HTTP 检索资源,而是如何处理异步调用和响应的副作用创建到整个应用程序。
- 所以现在这打开了您登记的几个选项。
基本上对于非常基本的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 哲学一致。