React Native i GraphQL w 2026: Apollo Client, Zapytania i Pytania Rekrutacyjne

Kompleksowy poradnik integracji GraphQL z React Native przy użyciu Apollo Client 4.0. Obejmuje zapytania, mutacje, buforowanie, obsługę offline i przygotowanie do rozmów rekrutacyjnych.

React Native i GraphQL w 2026: Apollo Client, Zapytania i Pytania Rekrutacyjne

GraphQL stał się preferowaną warstwą API dla aplikacji React Native wymagających elastycznego pobierania danych i efektywnego wykorzystania sieci. Apollo Client 4.0, wydany pod koniec 2025 roku, oferuje lżejszą architekturę z 20-30% mniejszymi pakietami i ulepszoną obsługą TypeScript zaprojektowaną specjalnie dla środowisk mobilnych.

Kluczowe zmiany w Apollo Client 4.0

Apollo Client 4.0 wyodrębnia eksporty specyficzne dla React do @apollo/client/react, obsługuje React 19 Suspense oraz React Compiler, a także zastępuje monolityczny ApolloError konkretnymi klasami błędów dla łatwiejszego debugowania.

Konfiguracja Apollo Client 4 w React Native

Proces instalacji pozostaje prosty. Apollo Client 4.0 współpracuje zarówno z projektami Expo, jak i czystym React Native.

bash
# Installation
npm install @apollo/client graphql

Inicjalizacja klienta wymaga HttpLink dla żądań sieciowych oraz InMemoryCache dla lokalnego zarządzania stanem.

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];
            },
          },
        },
      },
    },
  }),
});

Konfiguracja typePolicies obsługuje normalizację cache dla paginowanych danych - częste wymaganie w aplikacjach mobilnych z nieskończonym przewijaniem.

Opakowywanie aplikacji w ApolloProvider

Wzorzec provider łączy Apollo Client z drzewem komponentów React. Należy umieścić go na poziomie głównym, zazwyczaj w App.tsx lub layoucie 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 importuje hooki React z @apollo/client/react zamiast z głównego punktu wejścia. Ta zmiana zmniejsza rozmiar pakietu, gdy rdzeń klienta działa w kontekstach innych niż React.

Pisanie typowo-bezpiecznych zapytań GraphQL

GraphQL Code Generator generuje typy TypeScript ze schematu, eliminując niezgodności typów w runtime. Należy zainstalować go wraz z wtyczką klienta.

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

Konfiguracja codegen wskazuje na schemat i określa lokalizacje wyjściowe.

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;

Uruchomienie npx graphql-codegen generuje typowane węzły dokumentów, które konsumuje hook useQuery.

Pobieranie danych za pomocą useQuery

Hook useQuery zarządza stanami ładowania, błędami i aktualizacjami cache. Apollo Client 4.0 wprowadza API dataState dla bardziej przewidywalnych przejść stanów.

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}
    />
  );
}

Polityka pobierania cache-and-network wyświetla zbuforowane dane natychmiast, jednocześnie odświeżając z serwera. Ten wzorzec redukuje postrzeganą latencję w sieciach mobilnych.

Gotowy na rozmowy o React Native?

Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.

Mutacje i aktualizacje optymistyczne

Mutacje modyfikują dane serwera i aktualizują lokalny cache. Odpowiedzi optymistyczne zapewniają natychmiastową informację zwrotną przed potwierdzeniem zmiany przez serwer.

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 };
}

Metoda cache.modify bezpośrednio aktualizuje zbuforowane pola bez ponownego pobierania całego zapytania. To podejście minimalizuje żądania sieciowe w połączeniach komórkowych.

Obsługa błędów sieciowych w aplikacjach mobilnych

Apollo Client 4.0 zastępuje generyczny ApolloError konkretnymi klasami błędów. Statyczne metody .is() umożliwiają typowo-bezpieczną obsługę błędów.

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>;
}

Rozróżnianie błędów sieciowych od błędów GraphQL pozwala na różne strategie odzyskiwania: ponowienie próby dla przejściowych awarii, przekierowanie dla problemów z uwierzytelnianiem.

Wsparcie offline z persystencją cache

Aplikacje mobilne potrzebują dostępu offline do wcześniej pobranych danych. Biblioteka apollo3-cache-persist serializuje cache do 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
  });
}

Należy wywołać initializeCache przed renderowaniem aplikacji, aby przywrócić zbuforowane dane z dysku. Użytkownicy widzą ostatnio pobrane treści natychmiast, nawet bez dostępu do sieci.

Aktualizacje w czasie rzeczywistym za pomocą subskrypcji GraphQL

Subskrypcje przesyłają zdarzenia serwera do klienta przez WebSocket. Apollo Client 4.0 obsługuje nowszy protokół 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(),
});

Funkcja split kieruje operacje do odpowiedniego transportu na podstawie typu operacji.

Popularne pytania rekrutacyjne: React Native GraphQL

Rozmowy techniczne często badają zrozumienie kompromisów GraphQL specyficznych dla urządzeń mobilnych. Poniższe pytania pojawiają się często na stanowiskach React Native.

Dlaczego wybrać GraphQL zamiast REST dla aplikacji mobilnych?

GraphQL redukuje nadmierne pobieranie, zwracając tylko żądane pola. Jedno zapytanie zastępuje wiele endpointów REST, zmniejszając liczbę okrążeń przez połączenia komórkowe o wysokiej latencji. Typowany schemat umożliwia walidację w czasie kompilacji, wyłapując niezgodności API przed runtime.

Jak Apollo Client buforuje dane?

Apollo normalizuje odpowiedzi według __typename i id, przechowując każdą encję tylko raz. Zapytania odwołują się do znormalizowanych obiektów przez klucz cache. Ta deduplikacja oszczędza pamięć i zapewnia spójność: aktualizacja produktu na jednej liście aktualizuje go wszędzie.

Jakie polityki pobierania obsługuje Apollo Client?

PolitykaZachowaniePrzypadek użycia
cache-firstZwróć cache jeśli dostępny, inaczej pobierzDomyślna, minimalizuje żądania
cache-and-networkZwróć cache natychmiast, potem aktualizuj z sieciŚwieże dane z natychmiastowym wyświetlaniem
network-onlyZawsze pobieraj, aktualizuj cacheGdy nieaktualne dane są niedopuszczalne
cache-onlyNigdy nie pobieraj, błąd jeśli nie zbuforowaneTryb offline
no-cachePobierz bez buforowaniaDane wrażliwe

Jak działają aktualizacje optymistyczne?

Klient przewiduje wynik mutacji i aktualizuje cache przed odpowiedzią serwera. Jeśli serwer zwróci inny wynik, Apollo zastępuje dane optymistyczne rzeczywistą odpowiedzią. Jeśli mutacja się nie powiedzie, Apollo cofa do poprzedniego stanu.

Co powoduje problem N+1 w GraphQL?

Zagnieżdżone resolvery pobierające powiązane dane indywidualnie tworzą zapytania N+1. Żądanie listy 50 produktów z ich kategoriami uruchamia 1 zapytanie o produkty plus 50 zapytań o kategorie. DataLoader po stronie serwera grupuje je w jedno zapytanie.

Jak obsługiwać tokeny uwierzytelniania z Apollo Client?

Zalecane podejście wykorzystuje Apollo Link do dołączania tokenów do każdego żądania.

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}` : '',
    },
  };
});

Należy połączyć ten link przed HttpLink w konfiguracji klienta.

Debugowanie GraphQL w React Native

Apollo oferuje wiele opcji debugowania dla rozwoju React Native. Rozszerzenie Apollo dla VS Code zawiera wbudowane Client DevTools wyświetlające zawartość cache i historię zapytań.

Do samodzielnego debugowania Flipper integruje się z pluginem społeczności react-native-apollo-devtools. Ta wtyczka sprawdza stan cache, obserwuje zapytania w locie i odtwarza mutacje.

Inspekcja sieci przez React Native Debugger wymaga włączenia "Debug JS Remotely". Zakładka Network pokazuje wtedy payloady GraphQL z ciałami żądań i odpowiedzi.

Kluczowe wnioski dla mobilnego rozwoju GraphQL

  • Apollo Client 4.0 zmniejsza rozmiar pakietu o 20-30% dzięki pakowaniu ESM-first i wyodrębnionym eksportom React.
  • Polityka pobierania cache-and-network równoważy natychmiastowe wyświetlanie ze świeżością danych na wolnych połączeniach.
  • Aktualizacje optymistyczne zapewniają natychmiastową informację zwrotną; cache.modify unika niepotrzebnych ponownych pobrań.
  • Typowane klasy błędów w Apollo Client 4.0 umożliwiają specyficzną obsługę awarii sieciowych w porównaniu z błędami GraphQL.
  • Persystencja cache z apollo3-cache-persist umożliwia dostęp offline do wcześniej pobranych danych.
  • Subskrypcje GraphQL wymagają protokołu graphql-ws i konfiguracji split link.
  • Pytania rekrutacyjne koncentrują się na strategiach buforowania, politykach pobierania i kompromisach specyficznych dla urządzeń mobilnych, takich jak zapobieganie N+1.

Zacznij ćwiczyć!

Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.

Wyzwanie dnia

Znajdziesz błąd w React Native?

Prawdziwy fragment kodu, ukryty błąd, jedna próba dziennie. Bez konta, żeby spróbować.

Anthony Fillion-Maillet

Autor:

Anthony Fillion-Maillet

Założyciel SharpSkill

Programista fullstack od ponad 10 lat. Prowadzi SharpSkill i odpowiada za wszystko, co się tu ukazuje.

Zaktualizowano 20 sierpnia 2026

Udostępnij

Powiązane artykuły