React Native e GraphQL em 2026: Apollo Client, Queries e Perguntas de Entrevista

Guia completo para integrar GraphQL e Apollo Client 4.0 em aplicações React Native. Configuração, queries tipadas, mutations otimistas e perguntas técnicas de entrevista.

React Native e GraphQL com Apollo Client

GraphQL tornou-se a camada de API preferida para aplicações React Native que necessitam de busca de dados flexível e uso eficiente de rede. O Apollo Client 4.0, lançado no final de 2025, traz uma arquitetura mais enxuta com bundles 20-30% menores e suporte TypeScript aprimorado projetado especificamente para ambientes móveis.

Mudanças Principais do Apollo Client 4.0

O Apollo Client 4.0 desacopla as exportações específicas do React para @apollo/client/react, suporta React 19 Suspense e o React Compiler, e substitui o monolítico ApolloError por classes de erro específicas para melhor depuração.

Configurando Apollo Client 4 no React Native

O processo de instalação permanece simples. O Apollo Client 4.0 funciona tanto com Expo quanto com projetos bare React Native.

bash
# Installation
npm install @apollo/client graphql

A inicialização do cliente requer um HttpLink para requisições de rede e um InMemoryCache para gerenciamento de estado local.

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

A configuração typePolicies lida com a normalização de cache para dados paginados, um requisito comum em aplicações móveis com scroll infinito.

Envolvendo a Aplicação com ApolloProvider

O padrão provider conecta o Apollo Client à árvore de componentes React. Deve ser colocado no nível raiz, tipicamente em App.tsx ou no layout do 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>
  );
}

O Apollo Client 4.0 importa hooks React de @apollo/client/react em vez do ponto de entrada principal. Essa mudança reduz o tamanho do bundle quando o cliente core executa em contextos não-React.

Escrevendo Queries GraphQL com Tipagem

O GraphQL Code Generator produz tipos TypeScript a partir do schema, eliminando incompatibilidades de tipo em runtime. A instalação ocorre junto com o plugin do cliente.

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

A configuração do codegen aponta para o schema e especifica os locais de saída.

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;

Executar npx graphql-codegen gera nós de documento tipados que o hook useQuery consome.

Buscando Dados com useQuery

O hook useQuery gerencia estados de carregamento, erros e atualizações de cache. O Apollo Client 4.0 introduz a API dataState para transições de estado mais previsíveis.

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

A política de fetch cache-and-network exibe dados em cache imediatamente enquanto atualiza do servidor. Esse padrão reduz a latência percebida em redes móveis.

Pronto para mandar bem nas entrevistas de React Native?

Pratique com nossos simuladores interativos, flashcards e testes tecnicos.

Mutations e Atualizações Otimistas

Mutations modificam dados do servidor e atualizam o cache local. Respostas otimistas fornecem feedback instantâneo antes do servidor confirmar a mudança.

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

O método cache.modify atualiza diretamente campos em cache sem refazer a query completa. Essa abordagem minimiza requisições de rede em conexões celulares.

Tratamento de Erros de Rede em Aplicações Móveis

O Apollo Client 4.0 substitui o genérico ApolloError por classes de erro específicas. Os métodos estáticos .is() permitem tratamento de erros com type-safety.

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>Conexão falhou. Verifique sua conexão com a internet.</Text>
        <Button title="Tentar novamente" onPress={onRetry} />
      </View>
    );
  }

  // GraphQL validation or resolver errors
  if (GraphQLErrors.is(error)) {
    const firstError = error.graphQLErrors[0];
    if (firstError?.extensions?.code === 'UNAUTHENTICATED') {
      return <Text>Sessão expirada. Por favor, faça login novamente.</Text>;
    }
    return <Text>Requisição falhou: {firstError?.message}</Text>;
  }

  return <Text>Algo deu errado</Text>;
}

Distinguir erros de rede de erros GraphQL permite diferentes estratégias de recuperação: tentar novamente para falhas transitórias, redirecionar para problemas de autenticação.

Suporte Offline com Persistência de Cache

Aplicações móveis precisam de acesso offline a dados previamente buscados. A biblioteca apollo3-cache-persist serializa o cache para 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
  });
}

Chamar initializeCache antes de renderizar a aplicação restaura dados em cache do disco. Os usuários veem seu último conteúdo buscado imediatamente, mesmo sem acesso à rede.

Atualizações em Tempo Real com Subscriptions GraphQL

Subscriptions enviam eventos do servidor para o cliente via WebSocket. O Apollo Client 4.0 suporta o protocolo mais recente 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(),
});

A função split direciona operações para o transporte apropriado baseado no tipo de operação.

Perguntas Comuns de Entrevista: React Native GraphQL

Entrevistas técnicas frequentemente exploram a compreensão dos trade-offs específicos do GraphQL em mobile. As seguintes perguntas aparecem frequentemente em posições React Native.

Por que escolher GraphQL em vez de REST para aplicações móveis?

GraphQL reduz over-fetching ao retornar apenas os campos solicitados. Uma única query substitui múltiplos endpoints REST, reduzindo viagens de ida e volta em conexões celulares de alta latência. O schema tipado permite validação em tempo de compilação, detectando incompatibilidades de API antes da execução.

Como o Apollo Client faz cache de dados?

O Apollo normaliza respostas por __typename e id, armazenando cada entidade uma única vez. Queries referenciam objetos normalizados por chave de cache. Essa deduplicação economiza memória e garante consistência: atualizar um produto em uma lista o atualiza em todos os lugares.

Quais políticas de fetch o Apollo Client suporta?

PolíticaComportamentoCaso de Uso
cache-firstRetorna cache se disponível, senão fetchPadrão, minimiza requisições
cache-and-networkRetorna cache imediatamente, depois atualiza da redeDados frescos com exibição instantânea
network-onlySempre fetch, atualiza cacheQuando dados obsoletos são inaceitáveis
cache-onlyNunca fetch, falha se não estiver em cacheModo offline
no-cacheFetch sem cachearDados sensíveis

Como funcionam as atualizações otimistas?

O cliente prevê o resultado da mutation e atualiza o cache antes do servidor responder. Se o servidor retorna um resultado diferente, o Apollo substitui os dados otimistas pela resposta real. Se a mutation falha, o Apollo reverte para o estado anterior.

O que causa um problema N+1 em GraphQL?

Resolvers aninhados que buscam dados relacionados individualmente criam queries N+1. Solicitar uma lista de 50 produtos com suas categorias dispara 1 query de produtos mais 50 queries de categorias. DataLoader do lado do servidor agrupa estas em uma única query.

Como tratar tokens de autenticação com Apollo Client?

A abordagem recomendada usa um Apollo Link para anexar tokens a cada requisição.

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

Encadear este link antes do HttpLink na configuração do cliente.

Depuração de GraphQL no React Native

O Apollo fornece múltiplas opções de depuração para desenvolvimento React Native. A extensão Apollo para VS Code inclui DevTools do Cliente integradas que exibem conteúdos do cache e histórico de queries.

Para depuração independente, o Flipper integra com o plugin da comunidade react-native-apollo-devtools. Este plugin inspeciona o estado do cache, observa queries em andamento e reproduz mutations.

A inspeção de rede através do React Native Debugger requer habilitar "Debug JS Remotely". A aba Network então mostra payloads GraphQL com corpos de requisição e resposta.

Pontos-Chave para Desenvolvimento GraphQL Mobile

  • O Apollo Client 4.0 reduz o tamanho do bundle em 20-30% através de empacotamento ESM-first e exportações React desacopladas.
  • A política de fetch cache-and-network equilibra exibição instantânea com frescor de dados em conexões lentas.
  • Atualizações otimistas fornecem feedback imediato; cache.modify evita refetches desnecessários.
  • Classes de erro tipadas no Apollo Client 4.0 permitem tratamento específico para falhas de rede versus erros GraphQL.
  • Persistência de cache com apollo3-cache-persist habilita acesso offline a dados previamente buscados.
  • Subscriptions GraphQL requerem o protocolo graphql-ws e configuração de split link.
  • Perguntas de entrevista focam em estratégias de cache, políticas de fetch e trade-offs específicos de mobile como prevenção N+1.

Comece a praticar!

Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.

Desafio do dia

Você saberia encontrar o bug em React Native?

Um trecho real, um bug escondido, uma tentativa por dia. Sem conta para testar.

Anthony Fillion-Maillet

Escrito por

Anthony Fillion-Maillet

Fundador da SharpSkill

Desenvolvedor fullstack há mais de 10 anos. Dirige a SharpSkill e responde por tudo o que é publicado aqui.

Atualizado em 20 de agosto de 2026

Tags

#react-native
#graphql
#apollo-client
#typescript
#mobile

Compartilhar

Artigos relacionados