RTK报错:Cannot refetch a query that has not been started yet 求助
解决RTK Query报错:
Cannot refetch a query that has not been started yet. 问题背景
应用在Airbrake中多次触发报错:Cannot refetch a query that has not been started yet.,最初无法复现,曾怀疑是RTK Query的refetch()方法、pollingInterval配置,或是类似以下Effect代码调用refetch导致:
useEffect(() => { if (user?.team !== userTeamRef.current) { refetch(); userTeamRef.current = user?.team === undefined ? null : user.team; } }, [user?.team, refetch]);
复现场景
成功复现错误的场景:在Promise回调中调用refetch,示例代码如下:
const [joinTeam ] = useJoinTeamMutation(); const { refetch } = useGetTeam(slugName); const onClick = () => { leaveTeam().then((res: any) => { if (!res.error) { refetch(); } }); };
原因分析
RTK Query的refetch()方法仅能在查询已初始化(即组件已触发过该查询的请求)且查询实例仍处于有效上下文时调用。在Promise回调执行时,可能出现两种情况导致报错:
- 组件在Promise完成前已卸载,
refetch引用的查询实例已被销毁; - 查询本身从未被初始化(比如组件挂载后因条件判断未触发查询),此时
refetch没有对应的查询上下文。
解决方案
1. 校验组件挂载状态
使用useRef保存组件挂载状态,调用refetch前先确认组件仍处于挂载状态:
import { useRef, useEffect } from 'react'; // 组件内部定义 const isMounted = useRef(true); useEffect(() => { return () => { isMounted.current = false; }; }, []); const onClick = () => { leaveTeam().then((res: any) => { if (!res.error && isMounted.current) { refetch(); } }); };
2. 改用标签失效更新数据
利用RTK Query的标签系统,在操作成功后使对应查询标签失效,触发自动重新获取,替代直接调用refetch:
import { invalidateTags } from '@reduxjs/toolkit/query/react'; const dispatch = useDispatch(); const [leaveTeam] = useLeaveTeamMutation(); const { refetch } = useGetTeam(slugName); const onClick = () => { leaveTeam().then((res: any) => { if (!res.error) { // 假设useGetTeam查询的providesTags包含['Team'] dispatch(invalidateTags(['Team'])); } }); };
注:也可以在useLeaveTeamMutation的定义中直接配置invalidatesTags: ['Team'],无需手动调用dispatch
3. 检查查询初始化状态
通过RTK Query返回的status字段判断查询是否已初始化,仅在查询已启动时调用refetch:
const { refetch, status } = useGetTeam(slugName); const onClick = () => { leaveTeam().then((res: any) => { if (!res.error && status !== 'uninitialized') { refetch(); } }); };
内容的提问来源于stack exchange,提问作者AWIXOR
相关产品推荐
相关产品推荐

