Интерфейсы для входных данных мутаций
Допустим, у нас есть задача: создать мутацию для добавления нового пользователя. В GraphQL это будет выглядеть так:
mutation AddUser($input: AddUserInput!) {
addUser(input: $input) {
id
name
email
}
}
Мутация принимает аргумент input типа AddUserInput. В GraphQL-схеме AddUserInput может быть таким:
input AddUserInput {
name: String!
email: String!
}
Теперь, чтобы типизировать эту мутацию в TypeScript, мы определим соответствующие интерфейсы.
Интерфейс для входных данных
interface AddUserInput {
name: string; // Имя пользователя
email: string; // Email пользователя
}
Интерфейс для результата
Мутация возвращает данные о созданном пользователе: его id, name и email. Определим интерфейс для результата:
interface AddUserResult {
addUser: {
id: string; // Уникальный идентификатор пользователя
name: string; // Имя пользователя
email: string; // Email пользователя
};
}
Настройка мутации с Apollo Client
Теперь, когда у нас есть интерфейсы, типизируем мутацию в React-компоненте. Мы будем использовать Apollo-хук useMutation.
Импорт GraphQL-запроса
Сначала напишем саму мутацию в виде .graphql или .ts файла. Вот как она может выглядеть:
# src/graphql/mutations/addUser.graphql
mutation AddUser($input: AddUserInput!) {
addUser(input: $input) {
id
name
email
}
}
Использование в React-компоненте
Теперь подключим эту мутацию в React. Мы будем использовать ту самую магию TypeScript.
import { gql, useMutation } from '@apollo/client';
// GraphQL мутация
const ADD_USER = gql`
mutation AddUser($input: AddUserInput!) {
addUser(input: $input) {
id
name
email
}
}
`;
// Наши интерфейсы
interface AddUserInput {
name: string;
email: string;
}
interface AddUserResult {
addUser: {
id: string;
name: string;
email: string;
};
}
// Компонент
const AddUserComponent: React.FC = () => {
// Используем хук useMutation с типизацией
const [addUser, { data, loading, error }] = useMutation<AddUserResult, { input: AddUserInput }>(ADD_USER);
const handleSubmit = async () => {
try {
const response = await addUser({
variables: {
input: {
name: "John Doe",
email: "johndoe@example.com",
},
},
});
console.log("User added:", response.data?.addUser);
} catch (e) {
console.error("Error adding user:", e);
}
};
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h1>Add User</h1>
<button onClick={handleSubmit}>Add User</button>
{data && (
<div>
<p>Added User:</p>
<p>Name: {data.addUser.name}</p>
<p>Email: {data.addUser.email}</p>
</div>
)}
</div>
);
};
Детали типизации useMutation
Обратите внимание на следующие моменты:
- Первый аргумент хука указывает интерфейс результата мутации:
<AddUserResult>. - Второй аргумент — это интерфейс для переменных:
<{ input: AddUserInput }>. - Внутри метода
addUserмы передаем переменные через объектvariables.
Генерация типов с помощью Apollo Codegen
Ручная работа с интерфейсами может быть скучной (и подверженной человеческим ошибкам). А если схема GraphQL меняется, вам придется вручную обновлять все соответствующие интерфейсы. Чтобы избежать этого, мы можем использовать Apollo Codegen — инструмент для автоматической генерации типов.
Установите необходимые зависимости:
npm install @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations
Создайте файл конфигурации codegen.yml:
schema: "http://localhost:4000/graphql" # URL вашего GraphQL API
documents: "src/**/*.graphql" # Путь к файлам с запросами и мутациями
generates:
src/types/graphql.d.ts: # Куда сохранять сгенерированные типы
plugins:
- "typescript"
- "typescript-operations"
Теперь запустите генерацию типов:
npx graphql-codegen
Это создаст файл graphql.d.ts, содержащий типы для всех запросов, мутаций и их переменных. После этого можно просто импортировать нужные типы и использовать их в вашем компоненте.
Практическое применение: Do's and Don'ts
- DO: используйте типизацию переменных и результата, чтобы избежать багов при изменении данных.
- DON'T: никогда не игнорируйте типы, считая, что "и так сойдет". Типизация — ваш спасатель от неожиданностей на продакшене.
- DO: обновляйте интерфейсы или используйте генераторы (например, Apollo Codegen), чтобы типы всегда были актуальными.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ