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

Apollo Client React中条件执行useQuery的最优方案对比

条件获取GraphQL数据的最优方案分析

前提代码

我们有如下GraphQL查询及对应类型:

const GET_ITEM = gql`
  query GetItem($itemId: Int!) {
    item(where: { itemId: $itemId }) {
      name
    }
  }
`;
type TQuery = { item: string };
type TVariables = { itemId: number };

现在需要在组件中条件获取该数据,以下是两种实现方案,哪种更合理、更优?


方案一:useQuery + skip 参数

function Item({ itemId }: { itemId: number | undefined }) {
  const { data } = useQuery<TQuery, TVariables>(GET_ITEM, {
    variables: { itemId: itemId ?? 0 },
    skip: itemId === undefined,
  });

  return <> {data?.item} </>;
}

方案二:useLazyQuery + useEffect 手动触发

function Item({ itemId }: { itemId: number | undefined }) {
  const [fetchItem, { data }] = useLazyQuery<TQuery, TVariables>(GET_ITEM);

  useEffect(() => {
    if (itemId !== undefined) {
      fetchItem({ variables: { itemId } });
    }
  }, [itemId, fetchItem]);

  return <> {data?.item} </>;
}

结论:方案一更优,理由如下

  • 贴合API设计意图:useQuery本身就是为组件挂载后自动获取数据的场景设计的,通过skip参数控制查询是否执行,是Apollo官方推荐的条件查询写法,逻辑直接易懂。
  • 代码简洁,心智负担低:方案一不需要额外的useEffect手动触发请求,少了一层依赖维护的逻辑,代码更易读、易维护。
  • 内置能力更完善:useQuery会自动处理缓存复用、重复请求去重,还能直接提供加载、错误状态(示例中未体现,但实际开发中非常实用),这些能力在方案二中虽然也存在,但手动触发的方式会增加不必要的逻辑复杂度。
  • 避免潜在无效触发:方案二中需要维护useEffect的依赖数组,虽然fetchItem通常是稳定引用,但极端情况下可能因依赖变化导致不必要的重触发;而方案一的skip逻辑完全由Apollo内部管理,可靠性更高。

另外补充:方案一中的itemId ?? 0是冗余的,因为skip为true时变量不会被使用,可以优化为更严谨的写法:

const { data } = useQuery<TQuery, TVariables>(GET_ITEM, {
  variables: { itemId },
  skip: itemId === undefined,
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 20:03:19