React Native และ GraphQL ในปี 2026: Apollo Client, Query และคำถามสัมภาษณ์

บทเรียน React Native GraphQL ฉบับสมบูรณ์พร้อม Apollo Client 4.0 เรียนรู้การตั้งค่า query, mutation, caching และเตรียมพร้อมสำหรับคำถามสัมภาษณ์ API มือถือ

React Native และ GraphQL ในปี 2026: Apollo Client, Query และคำถามสัมภาษณ์

GraphQL กลายเป็น API layer ที่ได้รับความนิยมสำหรับแอปพลิเคชัน React Native ที่ต้องการการดึงข้อมูลที่ยืดหยุ่นและการใช้งานเครือข่ายที่มีประสิทธิภาพ Apollo Client 4.0 ซึ่งเปิดตัวในปลายปี 2025 นำเสนอสถาปัตยกรรมที่กระชับขึ้นพร้อมขนาด bundle ที่ลดลง 20-30% และการรองรับ TypeScript ที่ปรับปรุงเฉพาะสำหรับสภาพแวดล้อมมือถือ

การเปลี่ยนแปลงหลักใน Apollo Client 4.0

Apollo Client 4.0 แยก export เฉพาะ React ไปที่ @apollo/client/react รองรับ React 19 Suspense และ React Compiler และแทนที่ ApolloError แบบ monolithic ด้วย error class เฉพาะสำหรับการ debug ที่ดีขึ้น

การตั้งค่า Apollo Client 4 ใน React Native

กระบวนการติดตั้งยังคงตรงไปตรงมา Apollo Client 4.0 ทำงานได้ทั้งโปรเจกต์ Expo และ React Native bare

bash
# Installation
npm install @apollo/client graphql

การเริ่มต้น client ต้องการ HttpLink สำหรับ request เครือข่าย และ InMemoryCache สำหรับการจัดการ state ภายในเครื่อง

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 จัดการการ normalize cache สำหรับข้อมูลแบบ pagination ซึ่งเป็นข้อกำหนดทั่วไปในแอปมือถือที่มี infinite scroll

การครอบแอปพลิเคชันด้วย ApolloProvider

Pattern provider เชื่อมต่อ Apollo Client กับ component tree ของ React วางไว้ที่ระดับ root โดยปกติใน 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 import React hooks จาก @apollo/client/react แทนที่จะเป็น entry point หลัก การเปลี่ยนแปลงนี้ลดขนาด bundle เมื่อ core client ทำงานในบริบทที่ไม่ใช่ React

การเขียน GraphQL Query แบบ Type-Safe

GraphQL Code Generator สร้าง TypeScript types จาก schema กำจัดความไม่ตรงกันของ type ในขณะ runtime ติดตั้งพร้อมกับ client plugin

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

การกำหนดค่า codegen ชี้ไปที่ schema และระบุตำแหน่ง 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;

การรัน npx graphql-codegen จะสร้าง typed document nodes ที่ถูกใช้โดย hook useQuery

การดึงข้อมูลด้วย useQuery

Hook useQuery จัดการ loading states, errors และ cache updates Apollo Client 4.0 แนะนำ API dataState สำหรับการเปลี่ยน state ที่คาดการณ์ได้มากขึ้น

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 แสดงข้อมูลจาก cache ทันทีในขณะที่รีเฟรชจาก server Pattern นี้ลด latency ที่รับรู้ได้บนเครือข่ายมือถือ

พร้อมที่จะพิชิตการสัมภาษณ์ React Native แล้วหรือยังครับ?

ฝึกฝนด้วยตัวจำลองแบบโต้ตอบ, flashcards และแบบทดสอบเทคนิคครับ

Mutation และ Optimistic Updates

Mutation แก้ไขข้อมูล server และอัปเดต cache ภายในเครื่อง Optimistic response ให้ feedback ทันทีก่อนที่ server จะยืนยันการเปลี่ยนแปลง

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

Method cache.modify อัปเดต field ที่ cache ไว้โดยตรงโดยไม่ต้อง fetch query ทั้งหมดใหม่ วิธีนี้ลด request เครือข่ายบนการเชื่อมต่อมือถือ

การจัดการ Network Error ในแอปมือถือ

Apollo Client 4.0 แทนที่ ApolloError ทั่วไปด้วย error class เฉพาะ Method static .is() ช่วยให้การจัดการ 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>;
}

การแยกแยะ network error จาก GraphQL error ช่วยให้ใช้กลยุทธ์การกู้คืนที่แตกต่างกัน: retry สำหรับความล้มเหลวชั่วคราว, redirect สำหรับปัญหาการยืนยันตัวตน

การรองรับ Offline ด้วย Cache Persistence

แอปมือถือต้องการการเข้าถึง offline สำหรับข้อมูลที่ fetch ไว้ก่อนหน้า Library apollo3-cache-persist serialize cache ไปยัง 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 ก่อน render แอปเพื่อกู้คืนข้อมูล cache จาก disk ผู้ใช้เห็นเนื้อหาที่ fetch ล่าสุดทันที แม้ไม่มีการเข้าถึงเครือข่าย

การอัปเดต Real-Time ด้วย GraphQL Subscriptions

Subscription ส่ง event จาก server ไปยัง client ผ่าน WebSocket Apollo Client 4.0 รองรับ protocol 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 กำหนดเส้นทาง operation ไปยัง transport ที่เหมาะสมตามประเภท operation

คำถามสัมภาษณ์ที่พบบ่อย: React Native GraphQL

การสัมภาษณ์ทางเทคนิคมักทดสอบความเข้าใจเกี่ยวกับ tradeoff เฉพาะมือถือของ GraphQL คำถามต่อไปนี้ปรากฏบ่อยในตำแหน่ง React Native

ทำไมเลือก GraphQL แทน REST สำหรับแอปมือถือ?

GraphQL ลด over-fetching โดยส่งคืนเฉพาะ field ที่ร้องขอ Query เดียวแทนที่ endpoint REST หลายตัว ลด round trip ผ่านการเชื่อมต่อมือถือที่มี latency สูง Schema ที่มี type ช่วยให้ validation ตอน compile-time จับความไม่ตรงกันของ API ก่อน runtime

Apollo Client cache ข้อมูลอย่างไร?

Apollo normalize response ตาม __typename และ id โดยเก็บแต่ละ entity หนึ่งครั้ง Query อ้างอิง object ที่ normalize แล้วตาม cache key การขจัดความซ้ำซ้อนนี้ประหยัดหน่วยความจำและรับประกันความสอดคล้อง: การอัปเดตสินค้าในรายการหนึ่งจะอัปเดตทุกที่

Apollo Client รองรับ fetch policy อะไรบ้าง?

Policyพฤติกรรมกรณีการใช้งาน
cache-firstส่งคืน cache ถ้ามี ไม่งั้น fetchค่าเริ่มต้น ลด request
cache-and-networkส่งคืน cache ทันที จากนั้นอัปเดตจาก networkข้อมูลใหม่พร้อมการแสดงผลทันที
network-onlyfetch เสมอ อัปเดต cacheเมื่อข้อมูลเก่าไม่เป็นที่ยอมรับ
cache-onlyไม่ fetch เลย fail ถ้าไม่มี cacheโหมด offline
no-cacheFetch โดยไม่ cacheข้อมูลที่ละเอียดอ่อน

Optimistic updates ทำงานอย่างไร?

Client ทำนายผลลัพธ์ mutation และอัปเดต cache ก่อน server ตอบกลับ ถ้า server ส่งคืนผลลัพธ์ที่แตกต่าง Apollo แทนที่ข้อมูล optimistic ด้วย response จริง ถ้า mutation ล้มเหลว Apollo rollback ไปยัง state ก่อนหน้า

อะไรทำให้เกิดปัญหา N+1 ใน GraphQL?

Nested resolver ที่ fetch ข้อมูลที่เกี่ยวข้องทีละตัวสร้าง N+1 query การร้องขอรายการสินค้า 50 รายการพร้อมหมวดหมู่ trigger 1 query สินค้าบวก 50 query หมวดหมู่ DataLoader ฝั่ง server รวมสิ่งเหล่านี้เป็น query เดียว

จัดการ token ยืนยันตัวตนกับ Apollo Client อย่างไร?

วิธีที่แนะนำใช้ Apollo Link เพื่อแนบ token กับทุก 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}` : '',
    },
  };
});

เชื่อมต่อ link นี้ก่อน HttpLink ในการกำหนดค่า client

การ Debug GraphQL ใน React Native

Apollo มีตัวเลือก debug หลายอย่างสำหรับการพัฒนา React Native VS Code Apollo extension รวม Client DevTools ในตัวที่แสดงเนื้อหา cache และประวัติ query

สำหรับการ debug แบบ standalone, Flipper ผสานรวมกับ plugin ชุมชน react-native-apollo-devtools Plugin นี้ตรวจสอบ state cache, ติดตาม query ที่กำลังทำงาน และ replay mutation

การตรวจสอบเครือข่ายผ่าน React Native Debugger ต้องเปิด "Debug JS Remotely" Tab Network จากนั้นจะแสดง payload GraphQL พร้อม body request และ response

ประเด็นสำคัญสำหรับการพัฒนา Mobile GraphQL

  • Apollo Client 4.0 ลดขนาด bundle 20-30% ผ่านการ package แบบ ESM-first และแยก export React
  • Fetch policy cache-and-network สมดุลการแสดงผลทันทีกับความสดของข้อมูลบนการเชื่อมต่อช้า
  • Optimistic updates ให้ feedback ทันที; cache.modify หลีกเลี่ยง refetch ที่ไม่จำเป็น
  • Error class ที่มี type ใน Apollo Client 4.0 ช่วยให้จัดการเฉพาะสำหรับความล้มเหลวเครือข่ายเทียบกับ error GraphQL
  • Cache persistence ด้วย apollo3-cache-persist ช่วยให้เข้าถึง offline สำหรับข้อมูลที่ fetch ไว้ก่อนหน้า
  • GraphQL subscription ต้องการ protocol graphql-ws และการกำหนดค่า split link
  • คำถามสัมภาษณ์มุ่งเน้นกลยุทธ์ caching, fetch policy และ tradeoff เฉพาะมือถือเช่นการป้องกัน N+1

เริ่มฝึกซ้อมเลย!

ทดสอบความรู้ของคุณด้วยตัวจำลองสัมภาษณ์และแบบทดสอบเทคนิคครับ

ชาเลนจ์ประจำวัน

คุณหาบั๊กใน React Native เจอไหม

โค้ดจริงหนึ่งชิ้น บั๊กที่ซ่อนอยู่หนึ่งจุด วันละหนึ่งครั้ง ลองได้โดยไม่ต้องมีบัญชี

Anthony Fillion-Maillet

เขียนโดย

Anthony Fillion-Maillet

ผู้ก่อตั้ง SharpSkill

เป็นนักพัฒนาฟูลสแตกมากว่า 10 ปี ดูแล SharpSkill และรับผิดชอบทุกสิ่งที่เผยแพร่ที่นี่

อัปเดตเมื่อ 20 สิงหาคม 2569

แชร์

บทความที่เกี่ยวข้อง