RTK Query中如何在transformResponse复用其他查询缓存?
RTK Query 顺序查询并复用缓存数据的正确实现方式
你的原思路不可行,因为transformResponse函数只能拿到当前查询的响应、元数据和参数,无法直接访问getFirst查询的缓存数据,没法在里面直接用第一个查询的结果做转换。下面提供两种可行的解决方案:
方案一:组件层面控制查询顺序(推荐)
在组件中先获取第一个查询的数据,拿到结果后再触发第二个查询,把第一个查询的数据作为参数传给第二个查询,这样就能在transformResponse里直接使用。
修改API定义
const myApi = createApi({ reducerPath: 'myApi', baseQuery: fetchBaseQuery({ baseUrl: '/' }), endpoints: (builder) => ({ getFirst: builder.query({ query: () => '/getFirst', }), getSecond: builder.query({ // 接收第一个查询的数据作为参数(仅作为依赖标识,无需在请求中使用) query: (firstData) => '/getSecond', transformResponse: (response, meta, firstData) => { // 使用firstData转换响应数据 const transformedConfig = response.map(item => ({ ...item, // 用firstData中的字段增强配置 extraInfo: firstData.find(data => data.id === item.id)?.info })); return transformedConfig; }, }), }), }); export const { useGetFirstQuery, useGetSecondQuery } = myApi;
组件中使用
function MyComponent() { // 先获取第一个查询的数据 const { data: firstData, isLoading: firstLoading } = useGetFirstQuery(); // 仅当firstData存在时,触发第二个查询 const { data: secondData, isLoading: secondLoading } = useGetSecondQuery(firstData, { skip: !firstData // 无firstData时跳过查询 }); if (firstLoading || secondLoading) return <div>加载中...</div>; if (!firstData || !secondData) return <div>加载失败</div>; return <div>{/* 渲染处理后的数据 */}</div>; }
方案二:API层通过queryFn处理顺序查询
如果不想在组件里处理顺序逻辑,可以用queryFn自定义查询流程,在里面先尝试获取第一个查询的缓存,缓存不存在则主动发起第一个查询,再请求第二个并完成数据转换。
const myApi = createApi({ reducerPath: 'myApi', baseQuery: fetchBaseQuery({ baseUrl: '/' }), endpoints: (builder) => ({ getFirst: builder.query({ query: () => '/getFirst', }), getSecond: builder.query({ queryFn: async (_, { getState, dispatch }) => { // 尝试从缓存获取getFirst的数据 const firstCache = myApi.endpoints.getFirst.select()(getState()); let firstData = firstCache.data; // 缓存无数据时,主动发起getFirst查询 if (!firstData) { const firstResult = await dispatch(myApi.endpoints.getFirst.initiate()); if (firstResult.isError) { return { error: firstResult.error }; } firstData = firstResult.data; } // 发起第二个查询 const secondResult = await fetchBaseQuery({ baseUrl: '/' })({ url: '/getSecond' }); if (secondResult.error) { return { error: secondResult.error }; } // 用firstData转换第二个查询的响应 const transformedData = secondResult.data.map(item => ({ ...item, extraInfo: firstData.find(data => data.id === item.id)?.info })); return { data: transformedData }; }, }), }), });
组件中使用
这种方式下,组件只需调用第二个查询,内部会自动处理第一个查询的依赖:
function MyComponent() { const { data: secondData, isLoading } = useGetSecondQuery(); if (isLoading) return <div>加载中...</div>; if (!secondData) return <div>加载失败</div>; return <div>{/* 渲染处理后的数据 */}</div>; }
总结
- 原思路的核心问题是
transformResponse无法跨查询访问缓存,必须通过参数传递或在queryFn中主动获取缓存/发起查询解决。 - 方案一更直观,组件逻辑清晰,适合大多数场景;方案二把逻辑封装在API层,组件更简洁,但需要处理缓存和错误的细节。
内容的提问来源于stack exchange,提问作者Metaman
相关产品推荐
相关产品推荐

