如何将RTK Query API与Redux reducer、selector关联实现数据处理?
问题解答
1. 是否需要直接将useGetMaterialsQuery返回的data传入函数做转换?
这是可行的方案,适合转换逻辑仅在少数组件内使用的场景,不会修改RTK Query全局缓存中的原始数据。
如果希望转换逻辑复用、或者不想在组件内写重复转换代码,还有两种更符合RTK Query设计的实现方式:
- 在调用
useGetMaterialsQuery时传入selectFromResult参数,直接在hook层完成数据转换 - 基于RTK的
createSelector编写独立的选择器,从RTK Query的缓存切片中读取数据后处理为需要的格式
2. 是否可以新建reducer slice,将RTK Query获取的数据同步到该slice中,从而在selector中直接访问state.materials.byId?
技术上可以实现:你可以在enhanceEndpoints时给getMaterials添加onQueryStarted生命周期回调,在接口请求成功后dispatch自定义action把数据写入自己的materials切片。
但非常不推荐这种做法:相当于同一份数据在Store中存储了两份,会额外带来数据同步的维护成本,后续缓存失效、重新请求、手动刷新等场景都需要额外处理两份数据的一致性,极易出现bug。
3. 我是否对相关工具的使用存在本质认知误区?
存在小的认知偏差:RTK Query的核心设计逻辑是托管所有接口相关的缓存、请求状态、生命周期逻辑,所有接口返回的数据默认都会存储在你配置的[api.reducerPath]对应的Store节点下,不会直接挂载到State根节点。
你需要访问getMaterials接口的返回数据时,应该先从state[api.reducerPath].queries.getMaterials(对应你的接口缓存key)中读取归一化后的原始数据,再通过选择器转换为byId的格式,不需要额外新建Slice存储重复数据。
示例代码:复用Selector实现数据转换
import { createSelector } from '@reduxjs/toolkit' // 从RTK Query缓存中取getMaterials的返回结果 const selectMaterialsResult = api.endpoints.getMaterials.select() // 二次转换为需要的格式 const selectMaterialsById = createSelector( selectMaterialsResult, (result) => result.data?.byId ?? {} ) // 组件中使用 const materialsById = useSelector(selectMaterialsById)
或者直接在hook中转换:
const { data: materialsById } = useGetMaterialsQuery(undefined, { selectFromResult: (res) => ({ ...res, data: res.data?.byId ?? {} }) })
内容的提问来源于stack exchange,提问作者Evan
相关产品推荐
相关产品推荐

