React Query 显示错误端点数据问题排查求助
我正在开发一款多体育项目数据获取与渲染应用,采用React Query + Axios实现数据请求,封装了通用请求函数适配不同项目的API结构。
核心代码实现
URL与请求封装函数
const getBaseURL = (sport: Sports) => { switch (sport) { case "basketball": case "baseball": case "rugby": case "hockey": return `https://v1.${sport}.api-sports.io`; case "football": return `https://v3.football.api-sports.io`; default: return ""; } }; const getHost = (sport: Sports) => { switch (sport) { case "basketball": case "baseball": case "rugby": case "hockey": return `v1.${sport}.api-sports.io`; case "football": return `v3.football.api-sports.io`; default: return ""; } }; function createAxiosInstance(baseURL: string, headers: Record<string, string>) { return axios.create({ baseURL: baseURL, headers: headers, }); } export const getFixturesByDate = async (date: string, sport: Sports) => { const baseURL = getBaseURL(sport); const headers = { "x-rapidapi-host": getHost(sport), "x-rapidapi-key": process.env.RAPIDAPI_KEY ?? process.env.NEXT_PUBLIC_RAPIDAPI_KEY!, }; const axiosInstance = createAxiosInstance(baseURL, headers); switch (sport) { case "basketball": return ( await axiosInstance.get<APIResponse<Games<BasketballScores>>>( `/games?date=${date}` ) ).data.response; case "baseball": return ( await axiosInstance.get<APIResponse<Games<BaseballScores>>>( `/games?date=${date}` ) ).data.response; case "rugby": return ( await axiosInstance.get<APIResponse<GamesWithPeriods<number | null>>>( `/games?date=${date}` ) ).data.response; case "hockey": return ( await axiosInstance.get< APIResponse<GamesWithPeriodsAndEvents<number | null>> >(`/games?date=${date}`) ).data.response; case "football": return ( await axiosInstance.get<APIResponse<Fixtures>>(`/fixtures?date=${date}`) ).data.response; default: return undefined; } };
React Query自定义Hook
export function useFixturesByDate(date: string, sport: Sports) { return useQuery({ queryKey: [sport, "fixtures", date], queryFn: () => getFixturesByDate(date, sport), staleTime: 5 * 60 * 1000, enabled: !!date || !!sport, }); }
HomeFixtures组件
const HomeFixtures = ({ sport }: Props) => { const { status } = useStatusStore(); const { date } = useDateStore(); const { league } = useLeagueStore(); const formattedDate = format(date, "yyyy-MM-dd"); const { data, isFetching, isError, error } = useFixturesByDate( formattedDate, sport ); // rest of the code };
页面调用(Next.js App Router)
篮球页面:
<div className="h-[calc(100vh-150px)] overflow-y-auto px-6"> <HomeFixtures sport={"basketball"} /> </div>
棒球页面:
<div className="h-[calc(100vh-150px)] overflow-y-auto px-6"> <HomeFixtures sport={"baseball"} /> </div>
问题现象
切换体育项目页面时,自定义Hook虽被调用,但React Query DevTools仍显示前一项目(如篮球)的数据,仅手动点击重新获取才能加载当前项目的正确数据。
问题排查与解决方案
1. 修复useQuery的enabled条件
当前enabled: !!date || !!sport的逻辑存在错误:只要date或sport任一存在就启用请求,这会导致当其中一个参数无效时仍发起请求,甚至可能干扰新请求的触发。
应修改为同时满足date和sport有效才启用请求:
enabled: !!date && !!sport,
这样只有当两个参数都存在时,才会发起请求,避免无效请求干扰缓存逻辑。
2. 验证queryKey的唯一性
当前queryKey为[sport, "fixtures", date],理论上不同sport会生成不同的queryKey,不会共享缓存。可在useFixturesByDate中添加日志,确认切换页面时sport参数是否正确更新:
export function useFixturesByDate(date: string, sport: Sports) { console.log("Current sport:", sport); console.log("Query key:", [sport, "fixtures", date]); return useQuery({ // ... 其他配置 }); }
若日志显示sport未正确更新,需检查页面组件的props传递是否存在问题。
3. 确认组件渲染环境
确保HomeFixtures组件是客户端组件(在文件顶部添加'use client'指令),因为React Query的hooks仅能在客户端组件中使用。若为服务器组件,useQuery无法正常工作,会导致数据不更新。
4. 检查staleTime配置
当前staleTime为5分钟,这意味着数据在5分钟内会被认为是新鲜的,但由于不同sport的queryKey不同,不会复用旧数据。若仍存在缓存问题,可临时将staleTime设为0进行测试,排除缓存影响:
staleTime: 0,
内容的提问来源于stack exchange,提问作者Rayyan Alam

