React Native та GraphQL у 2026: Apollo Client, Запити та Питання на Співбесідах

Посібник з інтеграції GraphQL у React Native за допомогою Apollo Client 4.0. Охоплює запити, мутації, кешування, офлайн-підтримку та підготовку до технічних співбесід.

React Native та GraphQL у 2026: Apollo Client, Запити та Питання на Співбесідах

GraphQL став переважним API-шаром для застосунків React Native, що потребують гнучкого отримання даних та ефективного використання мережі. Apollo Client 4.0, випущений наприкінці 2025 року, пропонує легшу архітектуру з на 20-30% меншими бандлами та покращеною підтримкою TypeScript, спеціально розробленою для мобільних середовищ.

Ключові зміни в Apollo Client 4.0

Apollo Client 4.0 виносить React-специфічні експорти до @apollo/client/react, підтримує React 19 Suspense та React Compiler, а також замінює монолітний ApolloError конкретними класами помилок для кращого налагодження.

Налаштування Apollo Client 4 у React Native

Процес встановлення залишається простим. Apollo Client 4.0 працює як з Expo, так і з bare React Native проєктами.

bash
# Installation
npm install @apollo/client graphql

Ініціалізація клієнта вимагає HttpLink для мережевих запитів та InMemoryCache для локального управління станом.

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

const httpLink = new HttpLink({
  uri: 'https://api.example.com/graphql',
  // Enable text streaming for @defer and subscriptions
  fetchOptions: {
    reactNative: { textStreaming: true },
  },
});

export const apolloClient = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          // Merge paginated results
          products: {
            keyArgs: ['category'],
            merge(existing = [], incoming) {
              return [...existing, ...incoming];
            },
          },
        },
      },
    },
  }),
});

Конфігурація typePolicies обробляє нормалізацію кешу для пагінованих даних — поширену вимогу в мобільних застосунках з нескінченним прокручуванням.

Обгортання застосунку в ApolloProvider

Патерн provider з'єднує Apollo Client з деревом компонентів React. Його слід розміщувати на кореневому рівні, зазвичай в App.tsx або layout Expo Router.

App.tsxtsx
import { ApolloProvider } from '@apollo/client/react';
import { apolloClient } from './src/apollo/client';
import { RootNavigator } from './src/navigation';

export default function App() {
  return (
    <ApolloProvider client={apolloClient}>
      <RootNavigator />
    </ApolloProvider>
  );
}

Apollo Client 4.0 імпортує React-хуки з @apollo/client/react замість головної точки входу. Ця зміна зменшує розмір бандла, коли ядро клієнта працює в не-React контекстах.

Написання типобезпечних GraphQL-запитів

GraphQL Code Generator генерує TypeScript-типи зі схеми, усуваючи невідповідності типів під час виконання. Його слід встановити разом з клієнтським плагіном.

bash
# Install codegen tools
npm install -D @graphql-codegen/cli @graphql-codegen/client-preset

Конфігурація codegen вказує на схему та визначає розташування виводу.

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

const config: CodegenConfig = {
  schema: 'https://api.example.com/graphql',
  documents: ['src/**/*.tsx', 'src/**/*.ts'],
  generates: {
    './src/gql/': {
      preset: 'client',
      config: {
        documentMode: 'string',
      },
    },
  },
};

export default config;

Запуск npx graphql-codegen генерує типізовані вузли документів, які споживає хук useQuery.

Отримання даних за допомогою useQuery

Хук useQuery керує станами завантаження, помилками та оновленнями кешу. Apollo Client 4.0 представляє API dataState для більш передбачуваних переходів станів.

src/screens/ProductListScreen.tsxtsx
import { useQuery } from '@apollo/client/react';
import { graphql } from '../gql';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';

const GET_PRODUCTS = graphql(`
  query GetProducts($category: String!, $limit: Int, $offset: Int) {
    products(category: $category, limit: $limit, offset: $offset) {
      id
      name
      price
      imageUrl
    }
  }
`);

export function ProductListScreen({ category }: { category: string }) {
  const { data, loading, error, fetchMore } = useQuery(GET_PRODUCTS, {
    variables: { category, limit: 20, offset: 0 },
    // Fetch from cache first, then network
    fetchPolicy: 'cache-and-network',
    // Keep previous data while fetching new
    notifyOnNetworkStatusChange: true,
  });

  if (error) {
    return <Text>Error: {error.message}</Text>;
  }

  const loadMore = () => {
    fetchMore({
      variables: { offset: data?.products.length ?? 0 },
    });
  };

  return (
    <FlatList
      data={data?.products ?? []}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => <ProductCard product={item} />}
      onEndReached={loadMore}
      onEndReachedThreshold={0.5}
      ListFooterComponent={loading ? <ActivityIndicator /> : null}
    />
  );
}

Політика отримання cache-and-network негайно відображає кешовані дані, одночасно оновлюючи з сервера. Цей патерн зменшує відчутну затримку в мобільних мережах.

Готовий до співбесід з React Native?

Практикуйся з нашими інтерактивними симуляторами, flashcards та технічними тестами.

Мутації та оптимістичні оновлення

Мутації модифікують серверні дані та оновлюють локальний кеш. Оптимістичні відповіді забезпечують миттєвий зворотний зв'язок до того, як сервер підтвердить зміну.

src/hooks/useAddToCart.tstsx
import { useMutation } from '@apollo/client/react';
import { graphql } from '../gql';

const ADD_TO_CART = graphql(`
  mutation AddToCart($productId: ID!, $quantity: Int!) {
    addToCart(productId: $productId, quantity: $quantity) {
      id
      items {
        id
        product {
          id
          name
        }
        quantity
      }
      totalPrice
    }
  }
`);

export function useAddToCart() {
  const [addToCart, { loading }] = useMutation(ADD_TO_CART, {
    // Optimistic response for instant UI feedback
    optimisticResponse: ({ productId, quantity }) => ({
      addToCart: {
        __typename: 'Cart',
        id: 'current-cart',
        items: [],
        totalPrice: 0,
      },
    }),
    // Update cache after mutation
    update(cache, { data }) {
      if (!data?.addToCart) return;
      cache.modify({
        id: cache.identify({ __typename: 'Cart', id: 'current-cart' }),
        fields: {
          items: () => data.addToCart.items,
          totalPrice: () => data.addToCart.totalPrice,
        },
      });
    },
  });

  return { addToCart, loading };
}

Метод cache.modify безпосередньо оновлює кешовані поля без повторного запиту всього запиту. Цей підхід мінімізує мережеві запити на мобільних з'єднаннях.

Обробка мережевих помилок у мобільних застосунках

Apollo Client 4.0 замінює загальний ApolloError конкретними класами помилок. Статичні методи .is() забезпечують типобезпечну обробку помилок.

src/components/ErrorBoundary.tsxtsx
import { NetworkError, GraphQLErrors } from '@apollo/client/errors';
import { Text, Button, View } from 'react-native';

interface Props {
  error: Error;
  onRetry: () => void;
}

export function QueryErrorHandler({ error, onRetry }: Props) {
  // Network failure (offline, timeout, DNS)
  if (NetworkError.is(error)) {
    return (
      <View>
        <Text>Connection failed. Check your internet.</Text>
        <Button title="Retry" onPress={onRetry} />
      </View>
    );
  }

  // GraphQL validation or resolver errors
  if (GraphQLErrors.is(error)) {
    const firstError = error.graphQLErrors[0];
    if (firstError?.extensions?.code === 'UNAUTHENTICATED') {
      return <Text>Session expired. Please log in again.</Text>;
    }
    return <Text>Request failed: {firstError?.message}</Text>;
  }

  return <Text>Something went wrong</Text>;
}

Розрізнення мережевих помилок від помилок GraphQL дозволяє застосовувати різні стратегії відновлення: повторна спроба для тимчасових збоїв, перенаправлення для проблем з автентифікацією.

Офлайн-підтримка з персистенцією кешу

Мобільні застосунки потребують офлайн-доступу до раніше отриманих даних. Бібліотека apollo3-cache-persist серіалізує кеш в AsyncStorage.

src/apollo/persistence.tstypescript
import AsyncStorage from '@react-native-async-storage/async-storage';
import { persistCache } from 'apollo3-cache-persist';
import { apolloClient } from './client';

export async function initializeCache() {
  await persistCache({
    cache: apolloClient.cache,
    storage: AsyncStorage,
    maxSize: 1024 * 1024 * 5, // 5 MB limit
    debounce: 1000, // Write at most once per second
  });
}

Слід викликати initializeCache перед рендерингом застосунку для відновлення кешованих даних з диска. Користувачі бачать останній отриманий контент негайно, навіть без доступу до мережі.

Оновлення в реальному часі за допомогою GraphQL Subscriptions

Subscriptions надсилають серверні події клієнту через WebSocket. Apollo Client 4.0 підтримує новіший протокол graphql-ws.

src/apollo/client.tstypescript
import { split, HttpLink, ApolloClient, InMemoryCache } 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: 'https://api.example.com/graphql' });

const wsLink = new GraphQLWsLink(
  createClient({
    url: 'wss://api.example.com/graphql',
    connectionParams: async () => ({
      authToken: await getStoredToken(),
    }),
  })
);

// Route subscriptions to WebSocket, others to HTTP
const splitLink = split(
  ({ query }) => {
    const definition = getMainDefinition(query);
    return (
      definition.kind === 'OperationDefinition' &&
      definition.operation === 'subscription'
    );
  },
  wsLink,
  httpLink
);

export const apolloClient = new ApolloClient({
  link: splitLink,
  cache: new InMemoryCache(),
});

Функція split направляє операції до відповідного транспорту на основі типу операції.

Поширені питання на співбесідах: React Native GraphQL

Технічні співбесіди часто перевіряють розуміння компромісів GraphQL, специфічних для мобільних пристроїв. Наступні питання часто з'являються на позиціях React Native.

Чому обирати GraphQL замість REST для мобільних застосунків?

GraphQL зменшує надмірне отримання даних, повертаючи лише запитані поля. Один запит замінює кілька REST-ендпоінтів, зменшуючи кількість обходів через мобільні з'єднання з високою затримкою. Типізована схема забезпечує валідацію під час компіляції, виявляючи невідповідності API до виконання.

Як Apollo Client кешує дані?

Apollo нормалізує відповіді за __typename та id, зберігаючи кожну сутність лише один раз. Запити посилаються на нормалізовані об'єкти за ключем кешу. Ця дедуплікація економить пам'ять та забезпечує консистентність: оновлення продукту в одному списку оновлює його всюди.

Які політики отримання підтримує Apollo Client?

ПолітикаПоведінкаВипадок використання
cache-firstПовернути кеш, якщо доступний, інакше запитатиЗа замовчуванням, мінімізує запити
cache-and-networkПовернути кеш негайно, потім оновити з мережіСвіжі дані з миттєвим відображенням
network-onlyЗавжди запитувати, оновлювати кешКоли застарілі дані неприйнятні
cache-onlyНіколи не запитувати, помилка якщо не кешованоОфлайн-режим
no-cacheЗапитувати без кешуванняЧутливі дані

Як працюють оптимістичні оновлення?

Клієнт передбачає результат мутації та оновлює кеш до відповіді сервера. Якщо сервер повертає інший результат, Apollo замінює оптимістичні дані фактичною відповіддю. Якщо мутація не вдається, Apollo відкочується до попереднього стану.

Що спричиняє проблему N+1 у GraphQL?

Вкладені резолвери, що отримують пов'язані дані окремо, створюють N+1 запитів. Запит списку 50 продуктів з їхніми категоріями запускає 1 запит продуктів плюс 50 запитів категорій. DataLoader на стороні сервера групує їх в один запит.

Як обробляти токени автентифікації з Apollo Client?

Рекомендований підхід використовує Apollo Link для додавання токенів до кожного запиту.

src/apollo/authLink.tstypescript
import { setContext } from '@apollo/client/link/context';
import { getStoredToken } from '../auth/storage';

export const authLink = setContext(async (_, { headers }) => {
  const token = await getStoredToken();
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : '',
    },
  };
});

Цей link слід з'єднати перед HttpLink у конфігурації клієнта.

Налагодження GraphQL у React Native

Apollo пропонує кілька варіантів налагодження для розробки React Native. Розширення Apollo для VS Code включає вбудовані Client DevTools, що відображають вміст кешу та історію запитів.

Для автономного налагодження Flipper інтегрується з плагіном спільноти react-native-apollo-devtools. Цей плагін перевіряє стан кешу, спостерігає за запитами в процесі та відтворює мутації.

Інспекція мережі через React Native Debugger вимагає увімкнення "Debug JS Remotely". Вкладка Network тоді показує GraphQL-пейлоади з тілами запитів та відповідей.

Ключові висновки для мобільної розробки з GraphQL

  • Apollo Client 4.0 зменшує розмір бандла на 20-30% завдяки ESM-first пакуванню та винесеним React-експортам.
  • Політика отримання cache-and-network балансує миттєве відображення зі свіжістю даних на повільних з'єднаннях.
  • Оптимістичні оновлення забезпечують миттєвий зворотний зв'язок; cache.modify уникає непотрібних повторних запитів.
  • Типізовані класи помилок в Apollo Client 4.0 забезпечують специфічну обробку мережевих збоїв порівняно з помилками GraphQL.
  • Персистенція кешу з apollo3-cache-persist забезпечує офлайн-доступ до раніше отриманих даних.
  • GraphQL subscriptions вимагають протоколу graphql-ws та конфігурації split link.
  • Питання на співбесідах зосереджуються на стратегіях кешування, політиках отримання та компромісах, специфічних для мобільних пристроїв, таких як запобігання N+1.

Починай практикувати!

Перевір свої знання з нашими симуляторами співбесід та технічними тестами.

Щоденний виклик

Чи знайдеш ти помилку в React Native?

Справжній фрагмент коду, прихована помилка, одна спроба на день. Щоб спробувати, акаунт не потрібен.

Anthony Fillion-Maillet

Автор:

Anthony Fillion-Maillet

Засновник SharpSkill

Fullstack-розробник понад 10 років. Керує SharpSkill і відповідає за все, що тут публікується.

Оновлено 20 серпня 2026 р.

Поділитися

Пов'язані статті