Я использую следующий код для генерации хуков для моего 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
в кодогенерации. Это позволит вам преобразовывать результаты запроса непосредственно в экземпляры ваших классов.
Вот шаги, которые вам нужно выполнить:
-
Создайте папку для преобразований: Для начала создайте файл, где вы будете хранить ваш маппер.
// transformers.ts import { FundData } from './path/to/FundData'; // импортируйте ваш класс FundData export const transformFundData = (data: any): FundData => { return new FundData(data); };
-
Обновите ваш класс FundData: Добавьте необходимые поля в ваш класс FundData, чтобы соответствовать структуре данных, которую вы получаете из GraphQL.
// FundData.ts export class FundData { legalName: string; constructor(data: any) { this.legalName = data.legalName; // присваиваем значение из полученных данных } getFormattedLegalName(): string { return this.legalName.toUpperCase(); } }
-
Настройте конфигурацию для генерации хуков: Вам нужно указать дополнительный плагин для использования трансформации. Вот как будет выглядеть ваша конфигурация:
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;
-
Используйте преобразованные данные в компоненте: Теперь, когда вы будете вызывать ваш хук, используйте его с вашей трансформацией.
const { data } = useSearchFundDataQuery({ variables: { nameOrIsin: '123' } }); const fundDataInstance = data ? transformFundData(data.getFundData) : null; if (fundDataInstance) { const firstName = fundDataInstance.getFormattedLegalName(); console.log(firstName); // будет выведено в верхнем регистре }
Теперь генерация хуков и маппинг данных на ваш класс должны работать корректно. Ваша функция transformFundData
берет данные и создает экземпляр вашего класса FundData
, предоставляя доступ к его методам, как вы это и задумали.
Обратите внимание, что вы можете изменить структуру классов и трансформаций в соответствии с вашими требованиями.