React Query列表未刷新:更新订单后已修改项仍显示
问题分析
当前场景:通过useInfiniteQuery获取所有acceptedAt: null的订单列表;执行useMutation更新订单的acceptedAt字段后,已调用invalidateQueries标记列表查询失效,但更新后的订单仍留在列表中(仅acceptedAt被更新)。
问题根源在于mutation的onSuccess逻辑:
- 先调用
invalidateQueries触发列表重新获取,但同时通过setQueriesData手动将缓存中的目标订单替换为更新后的版本(此时该订单已不符合acceptedAt: null的筛选条件)。 - 手动更新缓存的操作先于服务器新数据返回生效,导致用户看到的列表中仍保留了已不符合条件的订单;即使后续服务器返回正确的过滤后列表,也可能被缓存的手动更新干扰。
解决方案
方案1:移除手动缓存更新,完全依赖服务器刷新
直接删除onSuccess中的setQueriesData逻辑,仅保留invalidateQueries。失效查询后,会从服务器重新获取最新的订单列表,自然过滤掉已更新acceptedAt的订单。
修改后的useOrderAccept代码:
export const useOrderAccept = (id: number) => { const { business } = useSellarCurrentBusiness(); const { user } = useFirebaseUser(); const queryClient = useQueryClient(); return useMutation({ mutationFn: () => apiV2Request({ user, business, method: "post", path: `orders/v2/${id}/accept`, }).then( (response) => apiV2AssertResponse(response) .data as OrderV2Dto.OrderAcceptResponseType, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: [user?.uid, business?.id, ServerStateKeys.Orders], }); }, }); };
方案2:手动更新缓存时移除目标订单(适合即时反馈场景)
如果希望在服务器响应后立即从列表中移除已更新的订单(无需等待重新获取),可以修改setQueriesData的逻辑,将符合条件的订单从缓存中删除,而非替换它。
修改后的onSuccess中的setQueriesData部分:
onSuccess: (response) => { queryClient.invalidateQueries({ queryKey: [user?.uid, business?.id, ServerStateKeys.Orders], }); queryClient.setQueriesData<InfiniteData<OrderListResponseType>>( { predicate: ({ queryKey }) => { return ( queryKey[0] === user?.uid && queryKey[1] === business?.id && queryKey[2] === ServerStateKeys.Orders && typeof queryKey[3] === "object" ); }, }, (data) => { if (!data?.pages) return data; return { ...data, pages: data.pages.map((page) => page.filter((order) => order.id !== response.id) ), }; }, ); },
这样既通过invalidateQueries保证服务器数据最终一致,又通过手动移除缓存中的订单实现即时UI反馈,避免用户看到不符合筛选条件的订单。
内容的提问来源于stack exchange,提问作者Jm3s
相关产品推荐
相关产品推荐

