React Native và GraphQL năm 2026: Apollo Client, Query và Câu hỏi Phỏng vấn

Hướng dẫn toàn diện React Native GraphQL với Apollo Client 4.0. Tìm hiểu cách thiết lập, query, mutation, caching và chuẩn bị cho các câu hỏi phỏng vấn API mobile.

React Native và GraphQL năm 2026: Apollo Client, Query và Câu hỏi Phỏng vấn

GraphQL đã trở thành lớp API được ưa chuộng cho các ứng dụng React Native cần truy xuất dữ liệu linh hoạt và sử dụng mạng hiệu quả. Apollo Client 4.0, phát hành cuối năm 2025, mang đến kiến trúc gọn nhẹ hơn với kích thước bundle giảm 20-30% cùng hỗ trợ TypeScript được cải thiện đặc biệt cho môi trường mobile.

Thay đổi chính trong Apollo Client 4.0

Apollo Client 4.0 tách các export dành riêng cho React sang @apollo/client/react, hỗ trợ React 19 Suspense và React Compiler, đồng thời thay thế ApolloError đơn khối bằng các class error cụ thể để debug tốt hơn.

Thiết lập Apollo Client 4 trong React Native

Quá trình cài đặt vẫn đơn giản. Apollo Client 4.0 hoạt động tốt với cả dự án Expo và React Native bare.

bash
# Installation
npm install @apollo/client graphql

Khởi tạo client yêu cầu HttpLink cho các request mạng và InMemoryCache để quản lý state cục bộ.

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

Cấu hình typePolicies xử lý chuẩn hóa cache cho dữ liệu phân trang, yêu cầu phổ biến trong ứng dụng mobile với infinite scroll.

Bọc Ứng dụng với ApolloProvider

Pattern provider kết nối Apollo Client với component tree của React. Đặt nó ở cấp root, thường là trong App.tsx hoặc 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 import React hooks từ @apollo/client/react thay vì entry point chính. Thay đổi này giảm kích thước bundle khi core client chạy trong các ngữ cảnh không phải React.

Viết GraphQL Query Type-Safe

GraphQL Code Generator tạo các type TypeScript từ schema, loại bỏ các lỗi không khớp type lúc runtime. Cài đặt cùng với client plugin.

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

Cấu hình codegen trỏ đến schema và xác định vị trí output.

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;

Chạy npx graphql-codegen tạo ra typed document nodes được sử dụng bởi hook useQuery.

Lấy Dữ liệu với useQuery

Hook useQuery quản lý loading states, errors và cache updates. Apollo Client 4.0 giới thiệu API dataState cho việc chuyển đổi state dễ dự đoán hơn.

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

Fetch policy cache-and-network hiển thị dữ liệu từ cache ngay lập tức trong khi làm mới từ server. Pattern này giảm độ trễ cảm nhận được trên mạng mobile.

Sẵn sàng chinh phục phỏng vấn React Native?

Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.

Mutation và Optimistic Updates

Mutation sửa đổi dữ liệu server và cập nhật cache cục bộ. Optimistic response cung cấp phản hồi tức thì trước khi server xác nhận thay đổi.

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

Phương thức cache.modify trực tiếp cập nhật các field được cache mà không cần fetch lại toàn bộ query. Cách tiếp cận này giảm thiểu các request mạng trên kết nối di động.

Xử lý Network Error trong Ứng dụng Mobile

Apollo Client 4.0 thay thế ApolloError chung bằng các class error cụ thể. Các phương thức static .is() cho phép xử lý error type-safe.

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

Phân biệt network error với GraphQL error cho phép các chiến lược khôi phục khác nhau: retry cho lỗi tạm thời, redirect cho vấn đề xác thực.

Hỗ trợ Offline với Cache Persistence

Ứng dụng mobile cần truy cập offline vào dữ liệu đã fetch trước đó. Thư viện apollo3-cache-persist serialize cache vào 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
  });
}

Gọi initializeCache trước khi render ứng dụng để khôi phục dữ liệu cache từ disk. Người dùng thấy nội dung đã fetch lần cuối ngay lập tức, ngay cả khi không có kết nối mạng.

Cập nhật Real-Time với GraphQL Subscriptions

Subscription đẩy các event từ server đến client qua WebSocket. Apollo Client 4.0 hỗ trợ giao thức graphql-ws mới hơn.

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

Hàm split điều hướng các operation đến transport phù hợp dựa trên loại operation.

Câu hỏi Phỏng vấn Thường gặp: React Native GraphQL

Phỏng vấn kỹ thuật thường kiểm tra hiểu biết về các đánh đổi đặc thù mobile của GraphQL. Các câu hỏi sau xuất hiện thường xuyên trong các vị trí React Native.

Tại sao chọn GraphQL thay vì REST cho ứng dụng mobile?

GraphQL giảm over-fetching bằng cách chỉ trả về các field được yêu cầu. Một query thay thế nhiều endpoint REST, giảm round trip qua kết nối di động có độ trễ cao. Schema có type cho phép validation compile-time, bắt lỗi không khớp API trước runtime.

Apollo Client cache dữ liệu như thế nào?

Apollo chuẩn hóa response theo __typenameid, lưu mỗi entity một lần. Query tham chiếu đến các object đã chuẩn hóa theo cache key. Việc loại bỏ trùng lặp này tiết kiệm bộ nhớ và đảm bảo tính nhất quán: cập nhật một sản phẩm trong một list sẽ cập nhật ở mọi nơi.

Apollo Client hỗ trợ những fetch policy nào?

PolicyHành viTrường hợp sử dụng
cache-firstTrả về cache nếu có, nếu không thì fetchMặc định, giảm thiểu request
cache-and-networkTrả về cache ngay, sau đó update từ networkDữ liệu mới với hiển thị tức thì
network-onlyLuôn fetch, update cacheKhi dữ liệu cũ không chấp nhận được
cache-onlyKhông bao giờ fetch, fail nếu không có cacheChế độ offline
no-cacheFetch mà không cacheDữ liệu nhạy cảm

Optimistic updates hoạt động như thế nào?

Client dự đoán kết quả mutation và cập nhật cache trước khi server phản hồi. Nếu server trả về kết quả khác, Apollo thay thế dữ liệu optimistic bằng response thực tế. Nếu mutation thất bại, Apollo rollback về state trước đó.

Điều gì gây ra vấn đề N+1 trong GraphQL?

Các nested resolver fetch dữ liệu liên quan riêng lẻ tạo ra N+1 query. Yêu cầu danh sách 50 sản phẩm với category của chúng kích hoạt 1 query sản phẩm cộng 50 query category. DataLoader phía server gộp chúng thành một query duy nhất.

Làm thế nào để xử lý token xác thực với Apollo Client?

Cách tiếp cận được khuyến nghị sử dụng Apollo Link để đính kèm token vào mọi request.

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

Nối link này trước HttpLink trong cấu hình client.

Debug GraphQL trong React Native

Apollo cung cấp nhiều tùy chọn debug cho phát triển React Native. VS Code Apollo extension bao gồm Client DevTools tích hợp hiển thị nội dung cache và lịch sử query.

Để debug độc lập, Flipper tích hợp với plugin cộng đồng react-native-apollo-devtools. Plugin này kiểm tra state cache, theo dõi các query đang chạy và replay các mutation.

Kiểm tra mạng qua React Native Debugger yêu cầu bật "Debug JS Remotely". Tab Network sau đó hiển thị payload GraphQL với body request và response.

Điểm chính cho Phát triển Mobile GraphQL

  • Apollo Client 4.0 giảm kích thước bundle 20-30% thông qua đóng gói ESM-first và tách export React.
  • Fetch policy cache-and-network cân bằng hiển thị tức thì với độ mới của dữ liệu trên kết nối chậm.
  • Optimistic updates cung cấp phản hồi tức thì; cache.modify tránh refetch không cần thiết.
  • Các class error có type trong Apollo Client 4.0 cho phép xử lý cụ thể cho lỗi mạng so với lỗi GraphQL.
  • Cache persistence với apollo3-cache-persist cho phép truy cập offline vào dữ liệu đã fetch trước đó.
  • GraphQL subscription yêu cầu giao thức graphql-ws và cấu hình split link.
  • Câu hỏi phỏng vấn tập trung vào chiến lược caching, fetch policy và các đánh đổi đặc thù mobile như ngăn chặn N+1.

Bắt đầu luyện tập!

Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.

Thử thách hôm nay

Bạn có tìm ra lỗi trong React Native không?

Một đoạn mã thật, một lỗi ẩn, mỗi ngày một lượt. Không cần tài khoản để thử.

Anthony Fillion-Maillet

Viết bởi

Anthony Fillion-Maillet

Người sáng lập SharpSkill

Lập trình viên fullstack hơn 10 năm. Anh điều hành SharpSkill và chịu trách nhiệm về mọi nội dung đăng tại đây.

Cập nhật ngày 20 tháng 8, 2026

Chia sẻ

Bài viết liên quan