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

TypeScript React中Apollo GraphQL数据响应属性访问优化方案咨询

React迁移TypeScript时简化Apollo useQuery类型处理的最佳实践

问题背景

正在将非TypeScript的React应用迁移至TypeScript,当前处理Apollo useQuery返回数据的方式是手动为每个查询定义响应接口,但需迁移的查询数量庞大,希望找到更高效的方案。同时,按照Apollo指引使用生成的gql函数时,出现了DocumentNode无效的编译错误。

当前手动实现流程:

  1. 用graphql-tag定义查询:
import gql from 'graphql-tag';

export const FETCH_COMMENTS = gql(`
  query GetComments($entityId: ID!, $context: String!) {
     commentsByEntityIdAndContext(entityId: $entityId, context: $context) {
       totalCount
       items {
         id
         createdByName
         createdDate
         value
       }
    }
  }
`);
  1. 手动声明响应接口并传入useQuery:
import { CommentsByEntityIdAndContextCollectionSegment } from '../src/generated/gql';

interface CommentsQueryResponse {
    commentsByEntityIdAndContext?: CommentsByEntityIdAndContextCollectionSegment
}

const { loading, error, data } = useQuery<CommentsQueryResponse>(FETCH_COMMENTS, {
    variables: { entityId: entityId, context: context },
    fetchPolicy: "cache-and-network",
    nextFetchPolicy: "cache-first"
});

核心解决方案:利用TypedDocumentNode自动推导类型

1. 修复类型生成配置

你当前生成的gql文件中documents数组为空,说明GraphQL Code Generator未正确扫描到查询文件。调整生成工具配置(如codegen.ts),确保生成带类型的TypedDocumentNode:

// codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: './path/to/your/schema.graphql', // 指向你的GraphQL Schema
  documents: './src/**/*.{ts,graphql}', // 扫描所有包含查询的TS/GraphQL文件
  generates: {
    './src/generated/gql/': {
      preset: 'client',
      presetConfig: {
        gqlTagName: 'gql', // 和代码中使用的查询标签保持一致
      },
      config: {
        typedDocumentNode: true, // 关键:启用TypedDocumentNode生成
      },
    },
  },
};

export default config;

2. 使用生成的gql函数定义查询

重新运行生成命令(如npm run generate)后,直接用生成的gql函数定义查询,它会自动返回带响应类型和变量类型的TypedDocumentNode:

import { gql } from '../src/generated/gql';

// FETCH_COMMENTS自动携带查询的完整类型信息
export const FETCH_COMMENTS = gql(`
  query GetComments($entityId: ID!, $context: String!) {
     commentsByEntityIdAndContext(entityId: $entityId, context: $context) {
       totalCount
       items {
         id
         createdByName
         createdDate
         value
       }
    }
  }
`);

3. 无需手动指定泛型,useQuery自动推导类型

使用生成的查询时,useQuery会自动从TypedDocumentNode中解析响应类型和变量类型,无需手动声明:

import { useQuery } from '@apollo/client';
import { FETCH_COMMENTS } from './your-queries-file';

const { loading, error, data } = useQuery(FETCH_COMMENTS, {
    variables: { entityId: '123', context: 'post' }, // 变量类型自动校验
    fetchPolicy: "cache-and-network",
    nextFetchPolicy: "cache-first"
});

// data自动拥有正确的类型,直接访问data?.commentsByEntityIdAndContext?.items即可

4. 解决之前的编译错误

之前的错误原因是生成工具未正确生成DocumentNode实例,修复方式:

  • 确保配置中的documents路径能覆盖所有查询文件
  • 启用typedDocumentNode选项,让生成工具输出合法的DocumentNode

临时简化方案(无需调整生成配置时)

如果暂时无法修改生成工具配置,可直接使用生成的查询类型,避免手动写接口:

import { useQuery } from '@apollo/client';
import { GetCommentsQuery } from '../src/generated/gql'; // 生成工具自动为GetComments查询生成的类型
import { FETCH_COMMENTS } from './your-queries-file';

const { loading, error, data } = useQuery<GetCommentsQuery>(FETCH_COMMENTS, {
    variables: { entityId: entityId, context: context },
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 09:35:38