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.

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.
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.
# Installation
npm install @apollo/client graphqlKhởi tạo client yêu cầu HttpLink cho các request mạng và InMemoryCache để quản lý state cục bộ.
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.
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.
# Install codegen tools
npm install -D @graphql-codegen/cli @graphql-codegen/client-presetCấu hình codegen trỏ đến schema và xác định vị trí output.
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.
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.
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.
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.
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.
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 __typename và id, 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?
| Policy | Hành vi | Trường hợp sử dụng |
|---|---|---|
cache-first | Trả về cache nếu có, nếu không thì fetch | Mặc định, giảm thiểu request |
cache-and-network | Trả về cache ngay, sau đó update từ network | Dữ liệu mới với hiển thị tức thì |
network-only | Luôn fetch, update cache | Khi dữ liệu cũ không chấp nhận được |
cache-only | Không bao giờ fetch, fail nếu không có cache | Chế độ offline |
no-cache | Fetch mà không cache | Dữ 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.
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-networkcâ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.modifytrá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-persistcho phép truy cập offline vào dữ liệu đã fetch trước đó. - GraphQL subscription yêu cầu giao thức
graphql-wsvà 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.
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ử.

Viết bởi
Anthony Fillion-MailletNgườ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

Hướng Dẫn Phát Triển Ứng Dụng React Native 2026: Xây Dựng Ứng Dụng Production và Câu Hỏi Phỏng Vấn
Hướng dẫn toàn diện về phát triển ứng dụng React Native 2026 bao gồm New Architecture, Expo SDK 56, Hermes V1, và các câu hỏi phỏng vấn dành cho developer React Native.

Phát triển ứng dụng React Native 2026: Hướng dẫn đầy đủ và câu hỏi phỏng vấn
Hướng dẫn toàn diện về phát triển ứng dụng React Native năm 2026. Tìm hiểu về New Architecture, JSI, Fabric, TurboModules và các câu hỏi phỏng vấn thường gặp.

React Native 0.87 va SwiftPM nam 2026: Build iOS Hien Dai va Cau Hoi Phong Van
Huong dan day du ve React Native 0.87 voi ho tro Swift Package Manager cho build iOS. Tim hieu cach chuyen doi tu CocoaPods, Strict TypeScript API va cac cau hoi phong van ky thuat.