Apollo Client

Для интеграции с GraphQL в приложении на JavaScript используется библиотека Apollo Client. Начинается работа с установкой необходимых пакетов:

npm install @apollo/client graphql

@apollo/client содержит основной функционал для работы с GraphQL, включая кэширование, управление состоянием и работу с подписками. Пакет graphql необходим для корректного парсинга запросов и мутаций.

После установки создается клиент:

import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client';

const client = new ApolloClient({
  link: new HttpLink({ uri: 'https://example.com/graphql' }),
  cache: new InMemoryCache(),
});
  • HttpLink — настраивает конечную точку GraphQL.
  • InMemoryCache — реализует кэширование запросов и оптимизацию повторных запросов.

Использование ApolloProvider

Для интеграции Apollo Client с React-приложением применяется компонент ApolloProvider. Он обеспечивает доступ к клиенту во всех дочерних компонентах:

import { ApolloProvider } from '@apollo/client';
import App from './App';

<ApolloProvider client={client}>
  <App />
</ApolloProvider>

Все компоненты, использующие GraphQL-запросы, должны находиться внутри ApolloProvider, чтобы получить доступ к клиенту.

Запросы данных с useQuery

Основной инструмент получения данных — хук useQuery:

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

const GET_USERS = gql`
  query GetUsers {
    users {
      id
      name
      email
    }
  }
`;

function UsersList() {
  const { data, loading, error } = useQuery(GET_USERS);

  if (loading) return <p>Загрузка...</p>;
  if (error) return <p>Ошибка: {error.message}</p>;

  return (
    <ul>
      {data.users.map(user => (
        <li key={user.id}>{user.name} ({user.email})</li>
      ))}
    </ul>
  );
}
  • gql — тег для определения GraphQL-запроса.
  • loading — состояние загрузки.
  • error — информация об ошибках.
  • data — возвращаемые данные.

Мутации с useMutation

Для изменения данных используется useMutation:

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

const ADD_USER = gql`
  mutation AddUser($name: String!, $email: String!) {
    addUser(name: $name, email: $email) {
      id
      name
      email
    }
  }
`;

function AddUserForm() {
  const [addUser, { data, loading, error }] = useMutation(ADD_USER);

  const handleSubmit = async (e) => {
    e.preventDefault();
    const form = e.target;
    const name = form.name.value;
    const email = form.email.value;

    await addUser({ variables: { name, email } });
    form.reset();
  };

  return (
    <form onSub mit={handleSubmit}>
      <input name="name" placeholder="Имя" />
      <input name="email" placeholder="Email" />
      <button type="submit">Добавить</button>
      {loading && <p>Отправка...</p>}
      {error && <p>Ошибка: {error.message}</p>}
    </form>
  );
}
  • variables — объект с параметрами запроса.
  • Хук возвращает функцию для вызова мутации и объект состояния.

Управление кэшированием

InMemoryCache позволяет настраивать стратегию кэширования:

const client = new ApolloClient({
  link: new HttpLink({ uri: '/graphql' }),
  cache: new InMemoryCache({
    typePolicies: {
      User: {
        keyFields: ['id'],
      },
      Query: {
        fields: {
          users: {
            merge(existing = [], incoming) {
              return [...existing, ...incoming];
            },
          },
        },
      },
    },
  }),
});
  • typePolicies — правила для конкретных типов данных.
  • keyFields — уникальные идентификаторы объектов.
  • merge — стратегия объединения новых и старых данных при повторных запросах.

Подписки через WebSocket

Для реализации real-time обновлений используется Apollo Client + WebSocket:

import { ApolloClient, InMemoryCache, split, HttpLink } from '@apollo/client';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { createClient } from 'graphql-ws';
import { getMainDefinition } from '@apollo/client/utilities';

const httpLink = new HttpLink({ uri: '/graphql' });
const wsLink = new GraphQLWsLink(createClient({ url: 'ws://localhost:4000/graphql' }));

const splitLink = split(
  ({ query }) => {
    const definition = getMainDefinition(query);
    return definition.kind === 'OperationDefinition' && definition.operation === 'subscription';
  },
  wsLink,
  httpLink
);

const client = new ApolloClient({
  link: splitLink,
  cache: new InMemoryCache(),
});
  • split — выбирает подходящий транспорт для запросов и подписок.
  • GraphQLWsLink — устанавливает соединение через WebSocket.

Обновление UI после мутаций

Apollo Client позволяет автоматически обновлять кэш после мутаций:

const [addUser] = useMutation(ADD_USER, {
  update(cache, { data: { addUser } }) {
    const existing = cache.readQuery({ query: GET_USERS });
    cache.writeQuery({
      query: GET_USERS,
      data: { users: [...existing.users, addUser] },
    });
  },
});
  • update — функция для изменения кэша после выполнения мутации.
  • Используется комбинация readQuery и writeQuery для синхронизации локального состояния с сервером.

Оптимистическое обновление

Для мгновенной реакции UI можно использовать optimisticResponse:

const [addUser] = useMutation(ADD_USER, {
  optimisticResponse: {
    addUser: {
      id: -1,
      name: 'Загрузка...',
      email: 'loading@example.com',
      __typename: 'User',
    },
  },
});
  • В UI данные появятся сразу, а реальный ответ сервера обновит их позже.
  • Значение id временное, чтобы избежать конфликтов с реальными объектами.

Ленивая загрузка данных

useLazyQuery позволяет запускать запрос не при рендере, а по событию:

const [getUsers, { data, loading, error }] = useLazyQuery(GET_USERS);

<button onCl ick={() => getUsers()}>Загрузить пользователей</button>
  • Идеально для поиска, фильтрации и динамических действий.

Управление ошибками

Apollo Client предоставляет гибкую обработку ошибок:

const { error } = useQuery(GET_USERS, {
  onError(err) {
    console.error('Ошибка запроса:', err);
  },
});
  • Можно обрабатывать глобально через Apollo Link или локально в хуках.
  • Разделение ошибок GraphQL и Network позволяет тонко настраивать поведение приложения.

Итоговые возможности

Apollo Client обеспечивает полный цикл работы с GraphQL:

  • Запросы и мутации с хуками useQuery, useMutation.
  • Кэширование с InMemoryCache и политиками типов.
  • Поддержка подписок для real-time данных.
  • Оптимистические обновления и контроль кэша после мутаций.
  • Ленивая загрузка данных и расширенное управление ошибками.

Эти возможности делают библиотеку незаменимым инструментом для современных React-приложений, где требуется гибкая работа с серверными данными и синхронизация UI.