React Native中RTK Query分页场景下删除产品的缓存同步问题
解决方案
方法:手动更新缓存(推荐)
在deleteProduct mutation中添加onQueryStarted方法,直接操作getProducts的缓存,移除被删除的产品项,无需重新发起请求即可让页面立即更新。
修改后的完整代码如下:
export const productApi = baseApi.injectEndpoints({ overrideExisting: true, endpoints: (builder) => ({ getProducts: builder.query({ query: (page = 1) => `url?page=${page}`, transformResponse: (response) => { return response.data; }, serializeQueryArgs: ({ endpointName }) => { return endpointName; }, merge: (currentCache, newItems) => { currentCache.data.push(...newItems.data); currentCache.links = newItems?.links; }, forceRefetch({ currentArg, previousArg }) { return currentArg !== previousArg; }, providesTags: (result) => result ? [ ...result.data.map(({ id }) => ({ type: 'Products', id })), { type: 'Products', id: 'PARTIAL-LIST' } // 保留整体列表标签,用于缓存操作 ] : [{ type: 'Products', id: 'PARTIAL-LIST' }], }), deleteProduct: builder.mutation({ query: (id) => ({ url: "products/delete", method: "POST", body: { id }, }), // 手动操作缓存 async onQueryStarted(id, { dispatch, queryFulfilled }) { try { await queryFulfilled; // 过滤掉缓存中已删除的产品 dispatch( productApi.util.updateQueryData('getProducts', undefined, (draft) => { draft.data = draft.data.filter(item => item.id !== id); }) ); } catch (err) { // 如果删除请求失败,可在此回滚缓存操作,避免页面数据与实际不一致 } }, // 保留标签失效逻辑作为兜底,防止缓存不一致 invalidatesTags: (result, error, id) => [ { type: 'Products', id }, ], }) }) });
原方案失效原因
你之前的配置中,getProducts通过serializeQueryArgs将所有分页请求的结果合并为单一缓存条目。当invalidatesTags标记单个产品id时,RTK Query无法自动从合并后的缓存列表中移除对应项——它只会标记缓存失效,但受forceRefetch逻辑限制,仅当page参数变化时才会重新请求,因此页面无法立即更新。
通过updateQueryData直接修改合并后的缓存列表,就能实现删除操作后页面即时刷新的效果。
额外注意事项
- 若删除请求存在失败可能,务必在
onQueryStarted的catch块中回滚缓存操作,避免页面显示与实际后端数据不符。 - 保留
PARTIAL-LIST标签,后续若需刷新整个产品列表,可通过失效该标签触发全量重新获取。
内容的提问来源于stack exchange,提问作者ttars
相关产品推荐
相关产品推荐

