React Query触发重复请求且返回旧响应的问题排查
问题根源与解决办法
1. 缓存更新逻辑写错了
你在useUpdatePost的onMutate里更新缓存的方式有问题:
queryClient.setQueryData(['posts', post_id], (oldData) => ({ ...oldData, data, }));
这里把更新的data嵌套成了旧数据的一个属性,导致缓存里的文章对象结构不对,父组件拿到的post.status还是旧状态,直到onSuccess触发的重新拉取完成,才会拿到正确数据。
正确的写法应该是直接把更新字段合并到原文章对象里:
queryClient.setQueryData(['posts', post_id], (oldData) => ({ ...oldData, ...data, // 把更新的字段直接合并进原对象 }));
改完之后,缓存里的文章状态会立刻变成published,父组件能马上渲染子组件,不用等后端请求返回。
2. 两次请求的来龙去脉
之前的错误流程是:
- 触发更新,
onMutate错误更新缓存,父组件判断post.status不是published,不渲染子组件 - 后端更新完成,
onSuccess触发refetchQueries,发起第一次请求 - 请求返回正确数据,缓存更新,父组件渲染子组件
- 子组件挂载后调用
useGetPost,发现缓存之前是错的,发起第二次请求
修复缓存更新逻辑后,父组件会在onMutate之后立刻渲染子组件,子组件的useGetPost会直接读取缓存里的正确数据,不会发起额外请求。而onSuccess里的refetchQueries是用来同步后端最新数据,确保缓存和后端一致,这属于正常的同步操作。
3. 更优方案:避免重复查询
父组件和子组件都查同一个文章ID,其实完全可以把父组件拿到的post直接传给子组件,不用子组件再发起查询:
// 父组件 {post.status === 'published' && ( <div className="margin-bottom"> <ChildComponent post={post} /> </div> )} // 子组件 const ChildComponent = ({ post }) => { return <div>{post.title}</div>; };
这样既彻底避免了重复请求,代码也更简洁高效。
内容的提问来源于stack exchange,提问作者kabukiman
相关产品推荐
相关产品推荐

