Сгенерировать хук с использованием кастомного сопоставления классов в graphql-codegen

Вопросы и ответы

Я использую следующий код для генерации хуков для моего GraphQL.

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

const config: CodegenConfig = {
  schema: 'http://localhost:5240/graphql',
  documents: ['features/graphql/queries/*.ts'],
  ignoreNoDocuments: true,
  generates: {
    './features/graphql/__generated__/apollo.ts': {
      plugins: [
        'typescript',
        'typescript-operations',
        'typescript-react-apollo',
      ],
      config: {
        withHooks: true,
        withHOC: false,
        withComponent: false,
        strictScalars: true,
        scalars: {
          Date: 'Date',
          JSON: 'string',
        },
        useTypeImports: true,

        avoidOptionals: true,
        maybeValue: 'T | null',
      },
    },
  },
}

export default config

Все это хорошо работает, я получаю сгенерированные хуки и все данные. Но я хотел бы сопоставить результат с пользовательским классом. Я, конечно, могу создать другой хук для того, чтобы получить его с типизацией, но было бы лучше, если бы сгенерированные хуки уже имели правильное сопоставление.

Мой запрос — это просто простой gql запрос.

export const SEARCH_FUND = gql`
  query searchFund($nameOrIsin: String!) {
    getFundData(nameOrIsin: $nameOrIsin) {
      legalName
    }
  }
`

Я хочу, чтобы этот запрос был сопоставлен с моим классом.

export class FundData {    
  constructor
  getFormattedLegalName(): string {
    return this.legalName.toUpperCase()
  }
}

И затем в моем коде иметь возможность обращаться к функции внутри класса.

  const { data } = useSearchFundDataQuery({ variables: { nameOrIsin: '123' } })
  const firstName = data?.getFundData[0].getFormattedLegalName()

Ответ

Для решения вашей задачи с использованием GraphQL Code Generator для создания хуков с правильной маппировкой результата на пользовательский класс, вам нужно воспользоваться функцией transform в кодогенерации. Это позволит вам преобразовывать результаты запроса непосредственно в экземпляры ваших классов.

Вот шаги, которые вам нужно выполнить:

  1. Создайте папку для преобразований: Для начала создайте файл, где вы будете хранить ваш маппер.

    // transformers.ts
    import { FundData } from './path/to/FundData'; // импортируйте ваш класс FundData
    
    export const transformFundData = (data: any): FundData => {
     return new FundData(data);
    };
  2. Обновите ваш класс FundData: Добавьте необходимые поля в ваш класс FundData, чтобы соответствовать структуре данных, которую вы получаете из GraphQL.

    // FundData.ts
    export class FundData {
     legalName: string;
    
     constructor(data: any) {
       this.legalName = data.legalName; // присваиваем значение из полученных данных
     }
    
     getFormattedLegalName(): string {
       return this.legalName.toUpperCase();
     }
    }
  3. Настройте конфигурацию для генерации хуков: Вам нужно указать дополнительный плагин для использования трансформации. Вот как будет выглядеть ваша конфигурация:

    import type { CodegenConfig } from '@graphql-codegen/cli'
    import { transformFundData } from './path/to/transformers'; // импортируйте функцию трансформации
    
    const config: CodegenConfig = {
     schema: 'http://localhost:5240/graphql',
     documents: ['features/graphql/queries/*.ts'],
     ignoreNoDocuments: true,
     generates: {
       './features/graphql/__generated__/apollo.ts': {
         plugins: [
           'typescript',
           'typescript-operations',
           'typescript-react-apollo',
         ],
         config: {
           withHooks: true,
           withHOC: false,
           withComponent: false,
           strictScalars: true,
           scalars: {
             Date: 'Date',
             JSON: 'string',
           },
           useTypeImports: true,
           avoidOptionals: true,
           maybeValue: 'T | null',
         },
         // Добавим новую настройку для трансформации
         plugins: [{
             "add": {
               "content": "import { transformFundData } from './path/to/transformers';" // импортируем функцию трансформации
             }
           },
           // другие плагины...
         ],
       },
     },
    }
    export default config;
  4. Используйте преобразованные данные в компоненте: Теперь, когда вы будете вызывать ваш хук, используйте его с вашей трансформацией.

    const { data } = useSearchFundDataQuery({ variables: { nameOrIsin: '123' } });
    const fundDataInstance = data ? transformFundData(data.getFundData) : null;
    
    if (fundDataInstance) {
     const firstName = fundDataInstance.getFormattedLegalName();
     console.log(firstName); // будет выведено в верхнем регистре
    }

Теперь генерация хуков и маппинг данных на ваш класс должны работать корректно. Ваша функция transformFundData берет данные и создает экземпляр вашего класса FundData, предоставляя доступ к его методам, как вы это и задумали.

Обратите внимание, что вы можете изменить структуру классов и трансформаций в соответствии с вашими требованиями.

Оцените материал
Добавить комментарий

Капча загружается...