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

如何使用Apollo的useQuery并发执行多个GraphQL查询

批量处理Apollo useQuery多日期范围查询的最优方案

问题背景

现有可正常运行的Apollo useQuery查询示例,仅处理dates数组的第一个日期范围:

const { data, loading, error } = useQuery(query, { variables: { fromDate: dates[0][0], toDate: dates[0][1] } });
if (loading) return "Loading...";
if (error) return <pre>{error.message}</pre>
if (data) console.log(data.token)
return <div>
  <p>{data.token[0].name}</p>
</div>

dates数组包含多个双元素日期范围:

const dates = [
  ["2022-07-01T00:00:00+00:00", "2022-07-16T00:00:00+00:00"], 
  ["2022-07-16T00:00:00+00:00", "2022-08-01T00:00:00+00:00"], // July
  ["2022-08-01T00:00:00+00:00", "2022-08-16T00:00:00+00:00"],
  ["2022-08-16T00:00:00+00:00", "2022-09-01T00:00:00+00:00"], // August
  ["2022-09-01T00:00:00+00:00", "2022-09-16T00:00:00+00:00"]]

由于无法循环调用useQuery,尝试Promise.all方案触发React错误(Object not valid as a React child),同时不想手动编写多份useQuery,需最优实现方式。


解决方案

方法一:修改GraphQL查询(最优)

如果后端支持,直接扩展查询以接受日期范围数组作为变量,一次性获取所有结果,仅需一次useQuery调用,效率最高。

示例查询定义

# 自定义输入类型(需后端同步支持)
input DateRangeInput {
  fromDate: String!
  toDate: String!
}

# 修改后的查询
query GetTokensByDateRanges($dateRanges: [DateRangeInput!]!) {
  tokensByDateRanges(dateRanges: $dateRanges) {
    dateRange {
      fromDate
      toDate
    }
    tokens {
      name
    }
  }
}

React组件代码

const { data, loading, error } = useQuery(GET_TOKENS_BY_DATE_RANGES, {
  variables: {
    dateRanges: dates.map(([from, to]) => ({ fromDate: from, toDate: to }))
  }
});

if (loading) return "Loading...";
if (error) return <pre>{error.message}</pre>;

return (
  <div>
    {data.tokensByDateRanges.map(({ dateRange, tokens }, index) => (
      <div key={index}>
        <h4>日期范围: {dateRange.fromDate} 至 {dateRange.toDate}</h4>
        <p>{tokens[0]?.name}</p>
      </div>
    ))}
  </div>
);

方法二:自定义子组件循环渲染

创建独立子组件封装单个日期范围的useQuery逻辑,父组件循环渲染子组件。此方案符合React Hooks规则,避免循环调用钩子。

子组件代码

const TokenDateRange = ({ fromDate, toDate }) => {
  const { data, loading, error } = useQuery(query, {
    variables: { fromDate, toDate }
  });

  if (loading) return <p>加载中...</p>;
  if (error) return <pre>{error.message}</pre>;

  return (
    <div>
      <p>{data.token[0].name}</p>
    </div>
  );
};

父组件调用

return (
  <div>
    {dates.map(([from, to], index) => (
      <TokenDateRange key={index} fromDate={from} toDate={to} />
    ))}
  </div>
);

方法三:useLazyQuery结合useEffect批量触发

使用useLazyQuery获取查询函数,在useEffect中批量触发所有查询,通过状态统一管理结果、加载和错误状态。

示例代码

import { useLazyQuery } from '@apollo/client';
import { useState, useEffect } from 'react';

const YourComponent = () => {
  const [getTokenData] = useLazyQuery(query);
  const [allData, setAllData] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  const [errors, setErrors] = useState([]);

  useEffect(() => {
    let isMounted = true;
    const fetchAllData = async () => {
      // 批量触发所有查询
      const queryPromises = dates.map(([from, to]) => 
        getTokenData({ variables: { fromDate: from, toDate: to } })
          .then(result => ({
            range: [from, to],
            data: result.data,
            error: result.error
          }))
      );

      const results = await Promise.all(queryPromises);
      if (!isMounted) return;

      // 分离成功结果和错误
      const successResults = results.filter(item => item.data);
      const errorResults = results.filter(item => item.error);

      setAllData(successResults);
      setErrors(errorResults);
      setIsLoading(false);
    };

    fetchAllData();
    return () => { isMounted = false; };
  }, []);

  if (isLoading) return "全部加载中...";
  if (errors.length > 0) {
    return (
      <div>
        <h3>部分查询失败:</h3>
        {errors.map((err, index) => (
          <pre key={index}>
            范围: {err.range.join(' 至 ')}
            错误: {err.error.message}
          </pre>
        ))}
      </div>
    );
  }

  return (
    <div>
      {allData.map(({ data, range }, index) => (
        <div key={index}>
          <p>范围: {range.join(' 至 ')} - {data.token[0].name}</p>
        </div>
      ))}
    </div>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:45:07