
RTK Query核心概念:Query与Mutation
rtk query作为redux toolkit的一部分,提供了一种高效且声明式的方式来管理应用程序中的数据获取和缓存。其核心在于区分两种主要的数据操作类型:query(查询)和mutation(变更)。
-
builder.query (查询):
- 用途:用于定义从服务器获取数据的操作。它通常期望是幂等的,即多次执行相同的查询不会产生不同的副作用。
- 行为:RTK Query会自动管理query的缓存。当其关联的标签被其他操作(通常是mutation)失效时,query会自动触发数据重取。
- 标签管理:通过providesTags来声明该query提供哪些类型的数据标签。
-
builder.mutation (变更):
- 用途:用于定义向服务器发送数据以修改其状态的操作,例如创建、更新或删除资源。mutation通常会产生副作用。
- 行为:mutation不会自动重取数据,但它可以在成功执行后通知RTK Query哪些数据已过时。
- 标签管理:通过invalidatesTags来声明在mutation成功后,哪些类型的数据标签应该被视为失效。
关键点:query和mutation的区分是基于它们逻辑上的作用(获取数据 vs. 修改数据),而非HTTP请求方法(GET vs. POST)。即使你的数据获取操作必须使用POST请求(例如出于安全考虑),它仍然应该被定义为query,因为它本质上是获取数据而不是修改服务器状态。
数据自动刷新机制
RTK Query的强大之处在于其智能的缓存和自动刷新机制,这主要依赖于providesTags和invalidatesTags的协同工作。
- 数据提供:当一个query(例如用于获取员工列表的getEmployees)被组件订阅并成功获取数据后,它会根据其providesTags: ['employees']配置,将这些数据标记为属于'employees'类型。这些数据会被缓存起来。
- 数据变更与失效:当一个mutation(例如用于删除员工的deleteEmployee)被执行并成功修改了服务器上的数据(删除了一个员工)后,它会根据invalidatesTags: ['employees']通知RTK Query,所有标记为'employees'的数据都已失效。
- 自动重取:RTK Query接收到失效通知后,会检查当前所有活跃的query订阅。如果getEmployees``query正在被某个组件使用,并且其提供的标签'employees'已被失效,RTK Query将自动触发getEmployees``query重新执行。这样,前端组件就能获取到最新的员工列表数据,而无需手动触发刷新。
正确实现示例
为了实现deleteEmployee操作后getEmployees列表的自动刷新,我们需要将getEmployees从mutation类型更改为query类型。
import { createApi } from '@reduxjs/toolkit/query/react';
import customFetchBase from './customFetchBase.js';
export const publicApi = createApi({
reducerPath: 'publicApi',
baseQuery: customFetchBase,
tagTypes: ['employees'], // 定义一个全局的标签类型
endpoints: builder => ({
// 将 getEmployees 定义为 query,因为它用于获取数据
getEmployees: builder.query({ // <-- 关键修改:从 builder.mutation 改为 builder.query
query: ({
formData = "defaultHashedDataString",
salt = "xyz",
pageIndex = 1
}) => ({
url: '/Hafez/Employee/Data',
method: 'POST', // 即使是 POST 请求,只要是获取数据就应是 query
body: {
RequestVerificationToken: salt,
FormData: formData,
currentPage: pageIndex + 1
}
}),
providesTags: ['employees'] // 此 query 提供 'employees' 标签的数据
}),
// deleteEmployee 保持为 mutation,因为它修改数据
deleteEmployee: builder.mutation({
query: ({ formData, salt }) => ({
url: '/Hafez/Employee/Delete',
method: 'POST',
body: { RequestVerificationToken: salt, FormData: formData }
}),
invalidatesTags: ['employees'] // 此 mutation 使 'employees' 标签的数据失效
})
})
});
export const {
useGetEmployeesQuery, // <-- 对应的 Hook 名称也从 Mutation 变为 Query
useDeleteEmployeeMutation
} = publicApi;通过上述修改,当deleteEmployee成功执行并使'employees'标签失效时,任何正在使用useGetEmployeesQuery的组件都将自动触发getEmployees重新获取数据,从而实现前端页面的实时更新,确保删除操作后列表数据的即时同步。
注意事项
- 逻辑优先于HTTP方法:再次强调,builder.query和builder.mutation的选择应基于操作的逻辑目的(获取数据 vs. 修改数据),而不是HTTP请求方法(GET、POST、PUT、DELETE等)。即使你的数据获取操作需要使用POST请求,它仍然是query。
- 标签类型的一致性:在tagTypes、providesTags和invalidatesTags中使用的标签名称必须保持一致。这是RTK Query识别和管理数据缓存的关键。不一致的标签会导致自动刷新机制失效。
-
Hook的选择:
- 与query对应的Hook是use[EndpointName]Query(例如useGetEmployeesQuery)。它会自动管理数据的获取、缓存、加载状态和错误处理。
- 与mutation对应的Hook是use[EndpointName]Mutation(例如useDeleteEmployeeMutation)。它返回一个包含触发函数(如deleteEmployee)、加载状态和错误信息的数组,需要手动调用触发函数来执行操作。
- 错误处理与加载状态:query和mutation的Hook都提供了丰富的状态(如isLoading, isFetching, isError, error, isSuccess等),便于在UI中展示加载指示器或错误消息。
总结
RTK Query通过query和mutation的清晰区分,结合强大的标签失效机制,为React应用提供了高效、声明式的数据管理方案。正确地将数据获取操作定义为query,并利用providesTags和invalidatesTags进行标签管理,是实现数据自动刷新和优化用户体验的关键。理解这一核心原理,即使面对诸如必须使用POST进行数据获取的特殊场景,也能灵活应对,构建健壮且响应迅速的前端应用。










