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

React Query中如何实现嵌套/条件链式API调用?

React Query 实现条件链式API调用的正确姿势

你的核心问题是违反了React Hook「只能在顶层调用」的规则,下面是几种符合规范且贴合需求的实现方式:

方案一:顶层声明所有Hook,通过enabled控制执行时机

把所有需要用到的React Query Hook都放在组件/自定义Hook的顶层,利用enabled选项控制它们是否触发,再根据条件选择对应结果返回:

function getCarDetails(car: CarSummary): UseQueryResult<CarDetails> {
  // 顶层声明所有查询,仅当车型匹配时才启用对应前置查询
  const hondaQuery = useHondaData(car, { enabled: car.make === 'honda' });
  const teslaQuery = useTeslaData(car, { enabled: car.make === 'tesla' });
  
  // 根据车型匹配对应的前置查询结果
  const preQueryResult = car.make === 'honda' ? hondaQuery : car.make === 'tesla' ? teslaQuery : null;

  // 前置查询出错时直接返回错误结果
  if (preQueryResult?.isError) {
    return preQueryResult as unknown as UseQueryResult<CarDetails>;
  }

  // 调用详情查询:通用车型直接执行,品牌车型等前置数据返回后再执行
  return useCarDetailsData(
    { 
      x: preQueryResult?.data?.y || 'generic' 
    },
    { 
      enabled: !preQueryResult || !!preQueryResult.data 
    }
  );
}

这种方式严格遵守Hook规则,逻辑和原代码完全对齐,前置查询只会在对应车型匹配时才发起请求,详情查询会自动等待前置数据就绪后再触发。

方案二:在单个useQuery中嵌套API调用

如果不想声明多个Hook,可以把整个链式逻辑封装到一个useQuery的queryFn中,只需要顶层调用一个Hook即可:

function getCarDetails(car: CarSummary): UseQueryResult<CarDetails> {
  return useQuery({
    queryKey: ['carDetails', car],
    queryFn: async () => {
      let xValue = 'generic';
      
      if (car.make === 'honda') {
        const hondaData = await fetchHondaData(car); // 这里用直接的API请求函数,而非useHondaData Hook
        xValue = hondaData.y;
      } else if (car.make === 'tesla') {
        const teslaData = await fetchTeslaData(car); // 同理,使用底层异步请求函数
        xValue = teslaData.y;
      }

      return fetchCarDetailsData({ x: xValue }); // 最终调用详情API
    },
  });
}

注意:这里必须使用直接封装的API请求函数(比如基于fetch/axios的异步函数),不能用对应的useHondaData类Hook——因为Hook不允许在异步函数内部调用。这种方式把所有逻辑收敛到一个查询中,错误会由React Query统一管理(前置API报错时,整个查询会直接标记为错误状态)。

方案三:使用useQueries管理多查询(复杂场景扩展)

如果需要更细粒度地跟踪多个查询状态,可以用useQueries批量管理,不过对你的需求来说稍显冗余,适合复杂场景参考:

function getCarDetails(car: CarSummary): UseQueryResult<CarDetails> {
  const queries = useQueries({
    queries: [
      { queryKey: ['hondaData', car], queryFn: () => fetchHondaData(car), enabled: car.make === 'honda' },
      { queryKey: ['teslaData', car], queryFn: () => fetchTeslaData(car), enabled: car.make === 'tesla' },
      { 
        queryKey: ['carDetails', car], 
        queryFn: async () => {
          const preData = car.make === 'honda' 
            ? queries[0].data 
            : car.make === 'tesla' 
              ? queries[1].data 
              : null;
          return fetchCarDetailsData({ x: preData?.y || 'generic' });
        },
        enabled: car.make !== 'honda' || !!queries[0].data,
      },
    ],
  });

  // 处理前置查询的错误
  if ((car.make === 'honda' && queries[0].isError) || (car.make === 'tesla' && queries[1].isError)) {
    return (car.make === 'honda' ? queries[0] : queries[1]) as unknown as UseQueryResult<CarDetails>;
  }
  // 返回最终的详情查询结果
  return queries[2];
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:47:24