apollo-client

apollo-client

使用 Apollo Client 4.x 建構 React 應用程式的指南。當您需要:(1) 在 React 專案中設定 Apollo Client,(2) 使用 hooks 撰寫 GraphQL 查詢或變更,(3) 設定快取或快取策略,(4) 使用反應式變數管理本地狀態,(5) 疑難排解 Apollo Client 錯誤或效能問題時,請使用此技能。

98星標
11分支
更新於 2026/7/14
SKILL.md
唯讀
名稱
apollo-client
描述

使用 Apollo Client 4.x 建構 React 應用程式的指南。當您需要:(1) 在 React 專案中設定 Apollo Client,(2) 使用 hooks 撰寫 GraphQL 查詢或變更,(3) 設定快取或快取策略,(4) 使用反應式變數管理本地狀態,(5) 疑難排解 Apollo Client 錯誤或效能問題時,請使用此技能。

Apollo Client 4.x 指南

Apollo Client 是一個全面的 JavaScript 狀態管理函式庫,讓您能夠使用 GraphQL 管理本地和遠端資料。4.x 版本帶來了改進的快取、更好的 TypeScript 支援以及 React 19 相容性。

整合指南

請根據您的應用程式設定選擇合適的整合指南:

每個指南都包含安裝步驟、設定以及針對該環境最佳化的框架特定模式。

快速參考

基本查詢

import { gql } from "@apollo/client";
import { useQuery } from "@apollo/client/react";

const GET_USER = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
    }
  }
`;

function UserProfile({ userId }: { userId: string }) {
  const { loading, error, data, dataState } = useQuery(GET_USER, {
    variables: { id: userId },
  });

  if (loading) return <p>載入中...</p>;
  if (error) return <p>錯誤:{error.message}</p>;

  // TypeScript 注意:為了更嚴格的型別縮小,您也可以在存取資料前檢查 `dataState === "complete"`
  return <div>{data?.user.name}</div>;
}

基本變更

import { gql } from "@apollo/client";
import { useMutation } from "@apollo/client/react";

const CREATE_USER = gql`
  mutation CreateUser($input: CreateUserInput!) {
    createUser(input: $input) {
      id
      name
    }
  }
`;

function CreateUserForm() {
  const [createUser, { loading, error }] = useMutation(CREATE_USER);

  const handleSubmit = async (name: string) => {
    await createUser({ variables: { input: { name } } });
  };

  return <button onClick={() => handleSubmit("John")}>建立使用者</button>;
}

Suspense 查詢

import { Suspense } from "react";
import { useSuspenseQuery } from "@apollo/client/react";

function UserProfile({ userId }: { userId: string }) {
  const { data } = useSuspenseQuery(GET_USER, {
    variables: { id: userId },
  });

  return <div>{data.user.name}</div>;
}

function App() {
  return (
    <Suspense fallback={<p>正在載入使用者...</p>}>
      <UserProfile userId="1" />
    </Suspense>
  );
}

參考檔案

特定主題的詳細文件:

  • TypeScript 程式碼產生 - GraphQL Code Generator 設定以獲得型別安全的操作
  • 查詢 - useQuery、useLazyQuery、輪詢、重新擷取
  • Suspense Hooks - useSuspenseQuery、useBackgroundQuery、useReadQuery、useLoadableQuery
  • 變更 - useMutation、樂觀 UI、快取更新
  • 片段 - 片段共置、useFragment、useSuspenseFragment、資料遮罩
  • 快取 - InMemoryCache、typePolicies、快取操作
  • 狀態管理 - 反應式變數、本地狀態
  • 錯誤處理 - 錯誤策略、錯誤連結、重試
  • 疑難排解 - 常見問題與解決方案

關鍵規則

查詢最佳實務

  • 每個頁面通常應該只有一個查詢,由共置的片段組成。 在所有非頁面元件中使用 useFragmentuseSuspenseFragment。使用 @defer 讓摺疊下方較慢的欄位稍後串流,避免阻塞頁面載入。
  • 片段是為了共置,而非重複使用。 每個片段應精確描述特定元件的資料需求,不應為了共用欄位而在元件間共享。請參閱片段參考以了解片段共置和資料遮罩的詳細資訊。
  • 使用非 Suspense hooks (useQueryuseLazyQuery) 時,務必在 UI 中處理 loadingerror 狀態。使用 Suspense hooks (useSuspenseQueryuseBackgroundQuery) 時,React 會透過 <Suspense> 邊界和錯誤邊界來處理。
  • 使用 fetchPolicy 控制每個查詢的快取行為
  • 使用 TypeScript 型別伺服器查詢函式和選項的文件(Apollo Client 有大量的 docblocks)

變更最佳實務

  • 如果 schema 允許,變更回傳值應回傳更新快取所需的一切。 不應需要手動更新或重新擷取。
  • 如果變更回應不足,請仔細權衡手動快取操作與重新擷取。手動更新可能遺漏伺服器邏輯。如有需要,可考慮樂觀更新搭配精細的重新擷取。
  • 在 UI 中優雅地處理錯誤
  • 謹慎使用 refetchQueries(優先讓快取自動更新)

快取最佳實務

  • 為沒有 id 欄位的型別設定 keyFields
  • 對於不包含識別碼且旨在將相關欄位分組在父項下的型別,透過設定 keyFields: false 停用正規化
  • 使用 typePolicies 處理分頁和計算欄位
  • 了解快取正規化以除錯問題
  • 為所有新應用程式啟用資料遮罩 - 防止元件存取不屬於它們的片段資料,強制執行適當的資料邊界並防止過度渲染

效能

  • 透過適當的欄位選擇避免過度擷取
  • 根據使用案例設定適當的 fetchPolicy
  • 使用 @defer 進行延遲查詢部分的增量傳遞,使用 @stream 進行串流列表欄位(@stream 在 Apollo Client 4.1+ 中可用)
  • 在現代應用程式中優先使用 Suspense hooks (useSuspenseQueryuseBackgroundQuery),以獲得更好的載入狀態處理和程式碼簡潔性

基本規則

  • 一律使用 Apollo Client 4.x 模式(非 v3 或更早版本)
  • 一律使用 ApolloProvider 包裹您的應用程式
  • 使用非 Suspense hooks 時,一律處理載入和錯誤狀態
  • 在現代應用程式中優先使用 Suspense hooks (useSuspenseQueryuseBackgroundQuery),以獲得更好的開發體驗
  • 切勿將 Apollo Client 儲存在 React 狀態中(使用模組層級或 context)
  • 對於讀取頻繁的資料,優先使用 cache-first;對於即時資料,使用 network-only
  • 使用 TypeScript 以獲得更好的 GraphQL 型別安全性
  • 實作適當的快取更新,而非重新擷取整個查詢
  • 在協同除錯 Apollo Client 問題時,建議人類查看 Apollo DevTools