使用useQuery时同组件双GET请求异常,拆分组件解决后求原因
问题原因分析
你遇到的问题核心是浏览器拦截了第二个请求,导致它卡在预检(OPTIONS)阶段,同时显示“Provisional Headers are shown”,拆分到独立组件后恢复正常,主要有这几个可能的原因:
1. useQuery 缓存Key重复
如果两个useQuery的缓存标识(第一个参数)完全一样,react-query会判定这是同一个请求,自动取消后发起的那个,转而复用缓存数据。这种情况下浏览器会直接终止第二个请求,就会出现你看到的现象。
- 检查两个
useQuery的第一个参数:
改成不同的key就能解决:// 错误示例:共用了相同的缓存key useQuery(['user'], fetchUserInfo) useQuery(['user'], fetchUserOrders)useQuery(['user-info'], fetchUserInfo) useQuery(['user-orders'], fetchUserOrders)
2. 第二个请求触发跨域预检但未通过
正常GET请求属于「简单请求」,不会触发OPTIONS预检,但如果你的第二个请求满足以下任一条件,浏览器会先发送OPTIONS预检:
- 带了非简单请求头(比如自定义的
X-Request-Id,或者Content-Type不是application/x-www-form-urlencoded、multipart/form-data、text/plain) - 请求URL包含特殊路径/参数,被浏览器判定为非简单请求
当预检请求被服务器拒绝(比如服务器没配置CORS允许该请求的预检),浏览器就会终止实际的GET请求,显示“Provisional Headers are shown”。
拆分组件后,可能因为渲染时机不同,请求头/参数被间接修正,避免了预检触发;或者react-query在组件分离后,请求执行逻辑被隔离,不会出现请求头被意外篡改的情况。
3. useQuery 执行时机冲突
如果两个useQuery的enabled配置存在依赖,或者其中一个请求的取消逻辑影响了另一个:
- 比如第一个请求的
enabled依赖第二个请求的返回值,导致第二个请求被提前取消 - 或者组件内的状态更新,触发其中一个请求重新执行,进而取消了另一个请求
这种情况下请求是被react-query主动取消的,浏览器会显示“Provisional Headers are shown”,因为请求没有正常走完流程。
4. 全局请求拦截器的干扰
如果你用了axios、fetch的全局拦截器,可能在同一个组件发两个请求时,拦截器对第二个请求做了错误修改(比如添加了不符合CORS规则的头),导致触发预检且失败。拆分组件后,拦截器的执行上下文变化,避开了这个问题。
验证建议
- 先排查缓存key是否唯一,这是最常见的触发原因
- 对比同一个组件和拆分组件时,第二个请求的请求头差异,看是否有非简单请求头
- 检查服务器CORS配置,确认是否允许该请求的OPTIONS预检
- 临时禁用全局请求拦截器,看问题是否消失
内容的提问来源于stack exchange,提问作者amir esfahanizadeh
相关产品推荐
相关产品推荐

