React-Query v4中useQueries钩子无限请求循环问题求助
解决useQueries无限请求循环问题
你的问题核心是每次组件渲染时都会生成全新的查询配置数组,导致react-query误判为查询参数发生变化,不断重复发起请求,最终触发API限流。以下是具体解决步骤:
1. 缓存查询配置数组
使用useMemo包裹查询配置的生成逻辑,确保只有当依赖的赛事ID数组变化时,才重新生成配置数组,避免不必要的重渲染和重复请求:
import { useMemo } from 'react'; import { useQueries, UseQueryOptions } from "@tanstack/react-query"; import { getMatchesFromApi, Match } from "./GetMatchesFromApi"; const allCompetitions = [2003, 2021]; function MatchesList() { // 用useMemo缓存查询配置,避免每次渲染生成新数组 const queries = useMemo(() => { return allCompetitions.map<UseQueryOptions<Match[]>>(competition => ({ queryKey: ["competition", competition], queryFn: () => getMatchesFromApi(competition), // 设置staleTime为Infinity,数据永远不失效,仅加载一次 staleTime: Infinity, // 可选:设置缓存时长,确保数据长期留存 cacheTime: 1000 * 60 * 60 * 24 // 缓存24小时 })); }, [allCompetitions]); // 仅当赛事列表变化时重新生成配置 const results = useQueries({ queries }); // 统一处理加载状态:只要有一个查询在加载,就显示加载中 const isLoading = results.some(result => result.isLoading); // 收集所有查询的错误信息 const errors = results.filter(result => result.error); if (isLoading) { return <div>Loading...</div>; } if (errors.length > 0) { return <div>加载失败:{errors.map(e => e.error?.message).join(', ')}</div>; } // 合并所有赛事的比赛数据 const allMatches = results.flatMap(result => result.data || []); return ( <div> <h3>所有赛事比赛</h3> <ul> {allMatches.map(match => ( <li key={match.id}>{match.homeTeam.shortName} - {match.awayTeam.shortName}</li> ))} </ul> </div> ); } export default MatchesList;
2. 关键配置说明
staleTime: Infinity:明确告诉react-query缓存的数据永远处于“新鲜”状态,不会自动发起重新请求,完全匹配你“仅懒加载一次”的需求。useMemo缓存查询数组:避免每次组件渲染时创建新的查询配置对象,防止react-query误判为查询参数变更而重复执行。- 状态统一处理:通过
some和flatMap简化多查询场景下的加载、错误、数据合并逻辑。
额外注意事项
- 如果
allCompetitions是动态获取的(比如来自props或组件状态),务必将其加入useMemo的依赖数组,确保赛事列表变化时能重新发起对应查询。 - 后续若需手动刷新数据,可调用单个查询的
refetch方法,而非依赖react-query的自动重新获取机制。
内容的提问来源于stack exchange,提问作者Leejjon
相关产品推荐
相关产品推荐

