React Query 的 useQuery 为什么在组件多次渲染时重复请求?

智慧 阅读 12

我在一个列表组件里用 useQuery 获取数据,明明传了相同的 queryKey,但每次父组件状态更新导致重渲染时,它都会重新发请求,不是应该缓存吗?

我试过加 staleTime,也确认了 queryKey 没变,但还是没用。是不是哪里配置错了?

const { data } = useQuery({
  queryKey: ['users'],
  queryFn: () => fetch('/api/users').then(res => res.json()),
  staleTime: 1000 * 60 * 5, // 5分钟
});
我来解答 赞 29 收藏
二维码
手机扫码查看
1 条解答
诗雅
诗雅 Lv1
你这个代码其实没写错,但问题出在 React Query 的默认行为上——它默认是 refetchOnWindowFocus: true,而且每次组件重渲染时如果检测到“可能 stale”,就会触发 refetch。

你加了 staleTime 是对的,但注意:React Query 的默认 staleTime 是 0!你写 5 分钟是对的,但要确认有没有被其他地方覆盖了(比如全局配置没生效,或者 queryClient 初始化时没传)。

不过更常见的坑是:父组件重渲染时,useQueryqueryFn 被重新创建了,哪怕 queryKey 没变,React Query 也会认为“函数变了,可能结果也变了”,于是触发请求。

所以关键点是:queryFn 必须用 useCallback 或者直接提成外部函数,保证引用稳定。

比如这样改:

const fetchUsers = () => fetch('/api/users').then(res => res.json());

function UserList() {
const { data } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
staleTime: 1000 * 60 * 5,
});

// ...
}


或者用 useCallback 包一下(虽然没必要,因为函数体没依赖):

const fetchUsers = useCallback(() => fetch('/api/users').then(res => res.json()), []);


再检查下你有没有全局配置里把 staleTime 覆盖成 0,或者有没有 useQuery 的其他参数(比如 enabledrefetchOnMount)在捣乱。

代码放这了,你试试看。要是还不行,八成是父组件传了个新对象当 queryKey(比如 ['users', someObject],每次 someObject 都是新引用),这种也容易踩。
点赞 4
2026-02-27 01:00