PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • AI для кодаНовое
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    GraphQL с нуля: схемы, резолверы и интеграция с React

    GraphQL с нуля: схемы, резолверы и интеграция с React

    Аватар автора GraphQL с нуля: схемы, резолверы и интеграция с React

    Антон Ларичев

    Иконка календаря14 июня 2026
    GraphQLReactApollo ClientBackendAPImiddleИконка уровня middle
    Картинка поста GraphQL с нуля: схемы, резолверы и интеграция с React

    Введение

    GraphQL — это язык запросов к API и среда выполнения для них, разработанная Facebook в 2012 году и открытая в 2015. В отличие от REST, где клиент получает фиксированный набор данных по URL, GraphQL позволяет клиенту запросить именно те поля, которые ему нужны. Это решает две классические проблемы REST: over-fetching (получение лишних данных) и under-fetching (необходимость нескольких запросов для одной сущности).

    В этой статье разберём три кита GraphQL: схемы (Schema), резолверы (Resolvers) и интеграцию с React через Apollo Client. После прочтения вы сможете поднять свой первый сервер и подключить его к фронтенду.

    Установка сервера

    Начнём с минимального сервера на Apollo Server. Установим зависимости:

    npm install @apollo/server graphql
    

    Создадим файл server.js:

    import { ApolloServer } from '@apollo/server';
    import { startStandaloneServer } from '@apollo/server/standalone';
    
    // Описание схемы на языке SDL
    const typeDefs = `#graphql
      type Book {
        id: ID!
        title: String!
        author: String!
      }
    
      type Query {
        books: [Book!]!
        book(id: ID!): Book
      }
    `;
    
    // Тестовые данные
    const books = [
      { id: '1', title: 'Чистый код', author: 'Роберт Мартин' },
      { id: '2', title: 'Совершенный код', author: 'Стив Макконнелл' },
    ];
    
    // Резолверы — функции, возвращающие данные для каждого поля
    const resolvers = {
      Query: {
        books: () => books,
        book: (_, { id }) => books.find((b) => b.id === id),
      },
    };
    
    const server = new ApolloServer({ typeDefs, resolvers });
    const { url } = await startStandaloneServer(server, { listen: { port: 4000 } });
    console.log(`Сервер готов: ${url}`);
    

    Схемы и типы

    Схема — это контракт между клиентом и сервером. Она описывает, какие данные доступны и какие операции можно выполнять. GraphQL поддерживает скалярные типы (Int, Float, String, Boolean, ID) и пользовательские объекты.

    Восклицательный знак (!) означает, что поле не может быть null. Квадратные скобки ([Book!]!) описывают массив, элементы которого тоже не могут быть null.

    Помимо Query существует Mutation для изменения данных и Subscription для подписки на события:

    type Mutation {
      addBook(title: String!, author: String!): Book!
      deleteBook(id: ID!): Boolean!
    }
    
    type Subscription {
      bookAdded: Book!
    }
    

    Резолверы

    Резолвер — это функция, которая возвращает значение для конкретного поля схемы. Сигнатура у всех резолверов одинаковая:

    resolver(parent, args, context, info)
    

    Где:

    • parent — результат родительского резолвера;
    • args — аргументы, переданные в поле;
    • context — общий объект для запроса (часто содержит юзера и подключение к БД);
    • info — мета-информация о запросе.

    Добавим мутацию:

    const resolvers = {
      Query: {
        books: () => books,
      },
      Mutation: {
        addBook: (_, { title, author }) => {
          const newBook = { id: String(books.length + 1), title, author };
          books.push(newBook);
          return newBook;
        },
      },
    };
    

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

    Book: {
      // Вычисляемое поле — короткое описание
      shortTitle: (parent) => parent.title.slice(0, 20),
    },
    

    Интеграция с React

    На фронте используем Apollo Client. Устанавливаем пакеты:

    npm install @apollo/client graphql
    

    Инициализируем клиент и оборачиваем приложение в провайдер:

    import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
    
    const client = new ApolloClient({
      uri: 'http://localhost:4000/',
      cache: new InMemoryCache(), // нормализованный кэш по __typename и id
    });
    
    export function Root() {
      return (
        <ApolloProvider client={client}>
          <BookList />
        </ApolloProvider>
      );
    }
    

    Запрашиваем данные хуком useQuery:

    import { gql, useQuery } from '@apollo/client';
    
    const GET_BOOKS = gql`
      query GetBooks {
        books {
          id
          title
          author
        }
      }
    `;
    
    export function BookList() {
      const { data, loading, error } = useQuery(GET_BOOKS);
    
      if (loading) return <p>Загрузка...</p>;
      if (error) return <p>Ошибка: {error.message}</p>;
    
      return (
        <ul>
          {data.books.map((book) => (
            <li key={book.id}>{book.title} — {book.author}</li>
          ))}
        </ul>
      );
    }
    

    Для мутаций есть хук useMutation. Он возвращает функцию-триггер и состояние выполнения:

    const ADD_BOOK = gql`
      mutation AddBook($title: String!, $author: String!) {
        addBook(title: $title, author: $author) {
          id
          title
        }
      }
    `;
    
    const [addBook, { loading }] = useMutation(ADD_BOOK, {
      // Обновляем список после добавления
      refetchQueries: [{ query: GET_BOOKS }],
    });
    

    Частые ошибки

    1. Проблема N+1. Когда резолвер вложенного поля делает запрос к БД на каждом элементе списка. Решение — батчинг через DataLoader, который собирает запросы за один тик и выполняет их одним SQL.

    2. Чрезмерно глубокие запросы. Клиент может запросить user → posts → comments → author → posts... и положить сервер. Ставьте ограничение через graphql-depth-limit или graphql-cost-analysis.

    3. Возврат всей сущности из мутации. Apollo Client автоматически обновит кэш только если в ответе мутации присутствует id и поля, которые уже есть в кэше. Не забывайте возвращать id.

    4. Отсутствие обработки ошибок на резолверах. Бросайте GraphQLError с понятным code в extensions, чтобы клиент мог корректно среагировать.

    5. Использование any в типах. Генерируйте TypeScript-типы из схемы через graphql-codegen — это даст автокомплит и проверку на этапе сборки.

    Заключение

    GraphQL даёт клиенту контроль над формой данных и снимает с бэкенда задачу по поддержке десятка эндпоинтов под разные экраны. Базовый стек прост: схема описывает контракт, резолверы достают данные, Apollo Client на фронте кэширует ответы и предоставляет хуки.

    Для продакшена изучите DataLoader, авторизацию через context, persisted queries и Federation, если у вас несколько сервисов. Начните с маленького сервера, подключите его к React-приложению и постепенно переносите фичи с REST — это самый безболезненный путь миграции.

    Иконка глаза590

    Комментарии

    0

    Постройте личный план изучения JavaScript с нуля - основы языка и практика для начинающих до уровня Middle — бесплатно!

    JavaScript с нуля - основы языка и практика для начинающих — часть карты развития Frontend, Backend, Mobile

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Продвинутый JavaScript

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    TypeScript с нуля

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Neovim

    Антон Ларичев
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее

    Похожие статьи

    Картинка поста GraphQL vs REST: как выбрать подход для вашего API
    Иконка аватараАнтон
    Иконка календаря28 августа 2026
    GraphQLRESTAPI+ 1middleИконка уровня middle

    GraphQL vs REST: как выбрать подход для вашего API

    GraphQL vs REST: сравниваем подходы к проектированию API — производительность, кэширование, версионирование — и разбираемся, что выбрать под конкретную задачу.

    Иконка чипа0
    Иконка глаза252
    Иконка комментариев0
    Картинка поста Docker для начинающих разработчиков: полное руководство
    Иконка аватараАнтон
    Иконка календаря12 сентября 2026
    DockerDevOpsКонтейнеризация+ 1juniorИконка уровня junior

    Docker для начинающих разработчиков: полное руководство

    Docker для начинающих разработчиков: разбираемся, что такое образы и контейнеры, как написать свой первый Dockerfile и запустить Docker Compose без лишней теории.

    Иконка чипа0
    Иконка глаза55
    Иконка комментариев0
    Картинка поста Vue vs React в 2026: какой фреймворк выбрать для проекта
    Иконка аватараАнтон
    Иконка календаря10 сентября 2026
    VueReactFrontend+ 1middleИконка уровня middle

    Vue vs React в 2026: какой фреймворк выбрать для проекта

    Сравниваем Vue и React в 2026 году: реактивность, Composition API vs хуки, Server Components и Vapor Mode на примерах кода.

    Иконка чипа0
    Иконка глаза103
    Иконка комментариев0
    Иконка чипа0