You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在react-query中正确实现useQueries以处理同组件多查询

问题根因

  1. 最初的双useQuery方案报错核心是isLoading和error的判断逻辑完全写反:
    你用了&&逻辑,需要两个查询同时加载才会显示Loading,只要其中一个查询先完成,就会跳过Loading判断进入渲染逻辑,此时另一个还未返回的查询对应的数据是undefined,子组件调用filter方法自然报错;同理error用&&也会导致只要一个查询正常、一个查询报错的场景下,直接进入渲染逻辑,报错数据为undefined。
  2. 改用useQueries后报错是因为你违反了两个规则:
  • React Hook只能在组件顶层或其他自定义Hook中调用,你将自定义HookuseData2的调用结果传给queryFn属于在普通函数上下文中调用Hook,本身就是不合法的
  • queryFn要求传入一个可执行的异步函数,你直接执行useData2后拿到的是useQuery返回的结果对象,自然会报queryFn is not a function的错误。
    另外你额外用useState存储react-query返回的数据属于冗余操作,react-query本身已经内置了响应式的数据状态管理,不需要额外用本地state同步,反而会引入状态更新时机不一致的问题。

方案1:修复原双useQuery方案(更简单,推荐)

首先修改自定义HookuseData,去掉冗余的setData传参,直接返回查询结果:

export function useData(queryId, chartId) {
  return useQuery(
    queryId,
    () => fetchData(chartId, "models").then((resp) => resp.Item.data)
  );
}

然后修改组件内的逻辑,修正Loading和错误判断:

export default function Component() {
  const { data: barData, error: errorBar, isLoading: loadingBar } = useData(
    "barQuery",
    "BAR_TEST_SINGLE"
  );
  const { data: lineData, error: errorLine, isLoading: loadingLine } = useData(
    "lineQuery",
    "LINE_TEST"
  );

  // 任意一个查询加载中就显示Loading
  const isLoading = loadingLine || loadingBar;
  // 任意一个查询报错就显示错误页
  const error = errorLine || errorBar;

  if (isLoading) return <LoadingSpinner title={title} />;
  if (error)
    return <InvalidStateAPI description={error.message} title={title} />;
  return (
    <>
        <Line data={lineData} />
        <Bar data={barData} />
    </>
  );
}

方案2:useQueries实现方案

如果要统一管理多个查询,也可以用useQueries实现,不需要嵌套自定义Hook,直接写查询逻辑即可:

export default function Component() {
  const results = useQueries([
    {
      queryKey: ["barQuery"],
      queryFn: () => fetchData("BAR_TEST_SINGLE", "models").then(resp => resp.Item.data),
    },
    {
      queryKey: ["lineQuery"],
      queryFn: () => fetchData("LINE_TEST", "models").then(resp => resp.Item.data),
    },
  ]);

  const isLoading = results.some(res => res.isLoading);
  const error = results.find(res => res.error)?.error;
  const [barData, lineData] = results.map(res => res.data);

  if (isLoading) return <LoadingSpinner title={title} />;
  if (error)
    return <InvalidStateAPI description={error.message} title={title} />;
  return (
    <>
        <Line data={lineData} />
        <Bar data={barData} />
    </>
  );
}

内容的提问来源于stack exchange,提问作者mmz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 14:15:00