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

解决ApolloError:未定义Fragment在client.query中的引入问题

问题:Apollo Client手动调用query时找不到Fragment的解决方案

问题背景

我在复杂项目中编写了如下代码:

import { gql } from '@apollo/client';

gql`
  fragment StuffTable on Stuff {
    id
    status
  }
`;

export const GetStuffDocument = gql`
  query GetStuff($id: ID!) {
    stuff(id: $id) {
      id
      ...StuffTable
    }
  }
`

// 另一个文件中的代码:
import { ApolloClient, useApolloClient } from '@apollo/client';
import GetStuffDocument from './OtherFile';

async function exportStuff(client: ApolloClient<unknown>): Promise<void> {
  const { data: metadata } = await client.query<GetStuffQuery>({
    query: GetStuffDocument,
  });
  // 其他逻辑,但在client.query步骤报错
}

function MyComponent() {
  const client = useApolloClient();
  
  return <button onClick={() => exportStuff(client)}>Download</button>
}

错误场景

点击导出按钮获取GraphQL数据生成CSV时,手动调用client.query抛出错误:

Uncaught (in promise) Error: Fragment StuffTable was used, but not defined
    at new ApolloError (index.ts:54:1)
    at QueryManager.ts:1043:1
    at both (asyncMap.ts:30:1)
    at asyncMap.ts:19:1
    at new Promise (<anonymous>)
    at Object.then (asyncMap.ts:19:1)
    at Object.next (asyncMap.ts:31:1)
    at notifySubscription (module.js:132:1)
    at onNotify (module.js:176:1)
    at SubscriptionObserver.next (module.js:225:1)

疑问

我想知道如何在手动调用的client.query中引入该Fragment解决错误,能否用以下方式实现?

const StuffTableFragment = gql`
  fragment StuffTable on Stuff {
    id
    status
  }
`;

// 然后调用:
const { data: metadata } = await client.query<GetStuffQuery>({
  query: GetStuffDocument,
  fragments: [StuffTableFragment],
});

查阅Apollo Client官方文档没找到相关帮助,特此求助。


解决方案

首先明确:你尝试的fragments参数在Apollo Client的client.query配置中不存在,这种写法无效。

下面是几种可行的解决方法:

方法1:将Fragment与Query定义在同一个gql模板中

把Fragment直接包含在导出的Query文档里,这样Apollo Client能自动识别关联的Fragment:

import { gql } from '@apollo/client';

export const GetStuffDocument = gql`
  fragment StuffTable on Stuff {
    id
    status
  }

  query GetStuff($id: ID!) {
    stuff(id: $id) {
      id
      ...StuffTable
    }
  }
`

这种方式最直接,确保Query和它依赖的Fragment被解析器同时处理。

方法2:导出Fragment并与Query合并

如果Fragment需要复用在多个Query中,可以单独导出Fragment,然后在调用client.query时,将Query和Fragment合并成一个完整的文档:

// 原文件中导出Fragment和Query
import { gql } from '@apollo/client';

export const StuffTableFragment = gql`
  fragment StuffTable on Stuff {
    id
    status
  }
`;

export const GetStuffDocument = gql`
  query GetStuff($id: ID!) {
    stuff(id: $id) {
      id
      ...StuffTable
    }
  }
`

// 在调用的文件中:
import { ApolloClient, useApolloClient, gql } from '@apollo/client';
import { GetStuffDocument, StuffTableFragment } from './OtherFile';

async function exportStuff(client: ApolloClient): Promise {
// 合并Query和Fragment
const combinedQuery = gql ${StuffTableFragment} ${GetStuffDocument} ;

const { data: metadata } = await client.query({
query: combinedQuery,
});
// 后续逻辑
}

## 方法3:在Apollo Client初始化时注册全局Fragment
如果Fragment会被多个地方频繁使用,可以在创建Apollo Client实例时,通过`typeDefs`注册全局Fragment:
```typescript
import { ApolloClient, InMemoryCache, gql } from '@apollo/client';

const StuffTableFragment = gql`
  fragment StuffTable on Stuff {
    id
    status
  }
`;

const client = new ApolloClient({
  uri: '你的GraphQL端点',
  cache: new InMemoryCache(),
  typeDefs: [StuffTableFragment], // 注册全局Fragment
});

这样所有使用该Fragment的Query都能自动识别,无需每次合并。

为什么你的尝试无效?

Apollo Client的client.query方法的配置参数中没有fragments这个选项,官方也从未支持过这种写法。Fragment必须和Query一起被包含在同一个GraphQL文档中,或者通过全局注册让客户端能找到它。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 20:45:47