web-data-fetching-graphql-apollo
Apollo ClientとGraphQLを活用し、データの取得・更新・キャッシュ管理を効率的に行い、画面表示の最適化やリアルタイム更新を実現するSkill。
📜 元の英語説明(参考)
Apollo Client GraphQL patterns - useQuery, useMutation, cache management, optimistic updates, subscriptions
🇯🇵 日本人クリエイター向け解説
Apollo ClientとGraphQLを活用し、データの取得・更新・キャッシュ管理を効率的に行い、画面表示の最適化やリアルタイム更新を実現するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o web-data-fetching-graphql-apollo.zip https://jpskill.com/download/10274.zip && unzip -o web-data-fetching-graphql-apollo.zip && rm web-data-fetching-graphql-apollo.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10274.zip -OutFile "$d\web-data-fetching-graphql-apollo.zip"; Expand-Archive "$d\web-data-fetching-graphql-apollo.zip" -DestinationPath $d -Force; ri "$d\web-data-fetching-graphql-apollo.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
web-data-fetching-graphql-apollo.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
web-data-fetching-graphql-apolloフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Apollo Client GraphQL パターン
クイックガイド: GraphQL API に Apollo Client を使用します。自動的な正規化されたキャッシュ、楽観的アップデート、リアルタイムサブスクリプションを提供します。型安全のために常に GraphQL Codegen を使用してください。適切なキャッシュ正規化のために、すべてのエンティティ型に
keyFieldsを設定してください。優雅な劣化のためにerrorPolicy: "all"を使用してください。v3.9+ は Suspense hooks を追加します。v4.0 は React のインポートを@apollo/client/reactに移動し、型安全なクエリ状態のためにdataStateを追加します。
<critical_requirements>
重要: この Skill を使用する前に
(GraphQL の型生成には必ず GraphQL Codegen を使用してください - GraphQL の TypeScript 型を手動で記述しないでください)
(キャッシュ正規化のために、すべての楽観的レスポンスに __typename と id を含める必要があります)
(すべてのエンティティ型に対して、適切な keyFields を持つ型ポリシーを設定する必要があります)
(すべてのタイムアウト、リトライ、ポーリングの値には、名前付き定数を使用する必要があります - マジックナンバーは使用しないでください)
</critical_requirements>
自動検出: Apollo Client, useQuery, useMutation, useSubscription, useSuspenseQuery, useLoadableQuery, useBackgroundQuery, useFragment, ApolloClient, InMemoryCache, gql, GraphQL, 楽観的アップデート, キャッシュポリシー, createQueryPreloader
使用する場合:
- GraphQL API からのデータ取得
- GraphQL サブスクリプションによるリアルタイムアップデート
- 正規化されたデータによる複雑なキャッシュ管理
- ミューテーションに対する楽観的 UI アップデート
- すでに GraphQL サーバーを使用しているアプリケーション
使用しない場合:
- REST API (代わりにデータ取得ソリューションを使用してください)
- キャッシュの必要がないシンプルな API (直接 fetch を検討してください)
- GraphQL Codegen を統合できない場合
カバーする主要なパターン:
- InMemoryCache と型ポリシーによるクライアント設定
- ローディング、エラー、データ状態を持つクエリのための useQuery / useLazyQuery
- 楽観的アップデート、cache.modify、cache.evict を持つ useMutation
- リアルタイム WebSocket データのための useSubscription
- fetchMore と relayStylePagination によるページネーション
- フラグメントのコロケーションと useFragment
- ローカルクライアント状態のためのリアクティブ変数
- Suspense hooks: useSuspenseQuery, useLoadableQuery, useBackgroundQuery, createQueryPreloader
詳細なリソース:
- examples/core.md - クライアント設定、useQuery、キャッシュアップデートを持つ useMutation
- examples/pagination.md - 無限スクロール、リレーページネーション型ポリシー
- examples/fragments.md - フラグメント定義、構成、コロケーション
- examples/error-handling.md - コンポーネントレベルおよびグローバルエラー処理
- examples/subscriptions.md - WebSocket リンク設定、キャッシュアップデートを持つ useSubscription
- examples/testing.md - MockedProvider、コンポーネントテスト、スキーマベースのテスト
- examples/suspense.md - v3.9+ Suspense hooks (useSuspenseQuery, useLoadableQuery, useBackgroundQuery)
- reference.md - 意思決定フレームワーク、API リファレンステーブル、アンチパターン
<philosophy>
Philosophy
Apollo Client は、インテリジェントな正規化されたキャッシュを提供する包括的な GraphQL クライアントであり、冗長なネットワークリクエストを削減し、コンポーネント間で UI の一貫性を保ちます。
コア原則:
- 正規化されたキャッシュ: データは型と ID によって一度だけ保存され、どこからでも参照されます - 1 か所を更新すると、UI 全体に反映されます
- 宣言的なデータ取得: コンポーネントは GraphQL を介して必要なデータを宣言し、Apollo はキャッシュ、重複排除、ネットワークを処理します
- 楽観的 UI: 期待される結果をすぐに表示し、サーバーエラー時に自動的にロールバックします
- 型安全: GraphQL Codegen はスキーマから TypeScript 型を生成します - レスポンス型を手動で記述しないでください
データフロー:
- コンポーネントは useQuery/useMutation を介してデータをリクエストします
- Apollo は InMemoryCache をチェックします (
__typename+keyFieldsで正規化) - キャッシュミスまたは古い場合、ネットワークから取得します
- レスポンスは正規化され、キャッシュに保存されます
- そのデータを監視しているすべてのコンポーネントが自動的に再レンダリングされます
</philosophy>
<patterns>
コアパターン
パターン 1: クライアントのセットアップと構成
InMemoryCache、キャッシュ正規化のための型ポリシー、エラー処理と認証のためのリンクチェーンで ApolloClient を構成します。環境変数は、GraphQL エンドポイントに対するフレームワークの規約を使用する必要があります。
const cache = new InMemoryCache({
typePolicies: {
User: { keyFields: ["id"] },
Product: { keyFields: ["sku"] }, // デフォルト以外の識別子
CartItem: { keyFields: false }, // 親に埋め込み、正規化しない
Query: {
fields: {
usersConnection: relayStylePagination(["filter"]),
},
},
},
});
重要な決定事項: keyFields は、エンティティがキャッシュ内でどのように識別されるかを決定します。 ["id"] (デフォルト)、["sku"] のようなカスタムフィールド、複合 ["authorId", "postId"]、または埋め込み型の場合は false を使用します。
認証リンク、エラーリンク、codegen 構成を含む完全なクライアント設定については、examples/core.md パターン 1 を参照してください。
パターン 2: データ取得のための useQuery
useQuery でデータ要件を宣言します。常にローディング、エラー、空の状態を処理します。 stale-while-revalidate の動作には cache-and-network を使用します。
const { data, loading, error, refetch } = useQuery<GetUsersQuery, GetUsersQueryVariables>(
GET_USERS,
{
variables: { limit: DEFAULT_PAGE_SIZE },
fetchPolicy: "cache-and-network",
skip: !shouldFetch,
}
);
if (loading && !data) return <Skeleton />;
if (error) return <Error message={error.message} onRetry={() => refetch()} />;
if (!data?.users?.length) return <EmptyState />;
このパターンの理由: loading && !data は、最初のロード時のみスケルトンを表示します (バックグラウンドリフレッシュではありません)。 cache-and-network は、ネットワークからリフレッシュしながら、キャッシュされたデータをすぐに表示します。
完全な useQuery および useLazyQuery の例については、examples/core.md パターン 2 を参照してください。
パターン 3: 楽観的アップデートとキャッシュアップデートを持つ useMutation
ミューテーションの場合、decid
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Apollo Client GraphQL Patterns
Quick Guide: Use Apollo Client for GraphQL APIs. Provides automatic normalized caching, optimistic updates, and real-time subscriptions. Always use GraphQL Codegen for type safety. Configure
keyFieldson every entity type for proper cache normalization. UseerrorPolicy: "all"for graceful degradation. v3.9+ adds Suspense hooks; v4.0 moves React imports to@apollo/client/reactand addsdataStatefor type-safe query state.
<critical_requirements>
CRITICAL: Before Using This Skill
(You MUST use GraphQL Codegen for type generation - NEVER write manual TypeScript types for GraphQL)
(You MUST include __typename and id in all optimistic responses for cache normalization)
(You MUST configure type policies with appropriate keyFields for every entity type)
(You MUST use named constants for ALL timeout, retry, and polling values - NO magic numbers)
</critical_requirements>
Auto-detection: Apollo Client, useQuery, useMutation, useSubscription, useSuspenseQuery, useLoadableQuery, useBackgroundQuery, useFragment, ApolloClient, InMemoryCache, gql, GraphQL, optimistic updates, cache policies, createQueryPreloader
When to use:
- Fetching data from GraphQL APIs
- Real-time updates with GraphQL subscriptions
- Complex cache management with normalized data
- Optimistic UI updates for mutations
- Applications already using a GraphQL server
When NOT to use:
- REST APIs (use your data fetching solution instead)
- Simple APIs without caching needs (consider fetch directly)
- When GraphQL Codegen cannot be integrated
Key patterns covered:
- Client setup with InMemoryCache and type policies
- useQuery / useLazyQuery for queries with loading, error, and data states
- useMutation with optimistic updates, cache.modify, and cache.evict
- useSubscription for real-time WebSocket data
- Pagination with fetchMore and relayStylePagination
- Fragment colocation and useFragment
- Reactive variables for local client state
- Suspense hooks: useSuspenseQuery, useLoadableQuery, useBackgroundQuery, createQueryPreloader
Detailed Resources:
- examples/core.md - Client setup, useQuery, useMutation with cache updates
- examples/pagination.md - Infinite scroll, relay pagination type policies
- examples/fragments.md - Fragment definitions, composition, colocation
- examples/error-handling.md - Component-level and global error handling
- examples/subscriptions.md - WebSocket link setup, useSubscription with cache updates
- examples/testing.md - MockedProvider, component tests, schema-based testing
- examples/suspense.md - v3.9+ Suspense hooks (useSuspenseQuery, useLoadableQuery, useBackgroundQuery)
- reference.md - Decision frameworks, API reference tables, anti-patterns
<philosophy>
Philosophy
Apollo Client is a comprehensive GraphQL client that provides intelligent normalized caching, reducing redundant network requests and keeping your UI consistent across components.
Core Principles:
- Normalized Cache: Data is stored once by type and ID, referenced everywhere - update in one place, UI reflects everywhere
- Declarative Data Fetching: Components declare what data they need via GraphQL, Apollo handles caching, deduplication, and network
- Optimistic UI: Show expected results immediately, rollback automatically on server error
- Type Safety: GraphQL Codegen generates TypeScript types from your schema - never write response types manually
Data Flow:
- Component requests data via useQuery/useMutation
- Apollo checks InMemoryCache (normalized by
__typename+keyFields) - If cache miss or stale, fetches from network
- Response is normalized and stored in cache
- All components watching that data re-render automatically
</philosophy>
<patterns>
Core Patterns
Pattern 1: Client Setup and Configuration
Configure ApolloClient with InMemoryCache, type policies for cache normalization, and link chain for error handling and auth. Environment variables should use your framework's convention for the GraphQL endpoint.
const cache = new InMemoryCache({
typePolicies: {
User: { keyFields: ["id"] },
Product: { keyFields: ["sku"] }, // Non-default identifier
CartItem: { keyFields: false }, // Embed in parent, don't normalize
Query: {
fields: {
usersConnection: relayStylePagination(["filter"]),
},
},
},
});
Key decisions: keyFields determines how entities are identified in cache. Use ["id"] (default), custom field like ["sku"], composite ["authorId", "postId"], or false for embedded types.
See examples/core.md Pattern 1 for complete client setup with auth link, error link, and codegen configuration.
Pattern 2: useQuery for Data Fetching
Declare data requirements with useQuery. Always handle loading, error, and empty states. Use cache-and-network for stale-while-revalidate behavior.
const { data, loading, error, refetch } = useQuery<GetUsersQuery, GetUsersQueryVariables>(
GET_USERS,
{
variables: { limit: DEFAULT_PAGE_SIZE },
fetchPolicy: "cache-and-network",
skip: !shouldFetch,
}
);
if (loading && !data) return <Skeleton />;
if (error) return <Error message={error.message} onRetry={() => refetch()} />;
if (!data?.users?.length) return <EmptyState />;
Why this pattern: loading && !data shows skeleton only on initial load (not background refetch). cache-and-network shows cached data immediately while refreshing from network.
See examples/core.md Pattern 2 for complete useQuery and useLazyQuery examples.
Pattern 3: useMutation with Optimistic Updates and Cache Updates
For mutations, decide between three cache update strategies: optimistic response (instant UI), update callback with cache.modify (manual cache update), or refetchQueries (simple but costs a network request).
const [createPost] = useMutation(CREATE_POST, {
optimisticResponse: {
createPost: {
__typename: "Post", // REQUIRED for normalization
id: `temp-${Date.now()}`, // Temporary ID, replaced by server response
title,
content,
},
},
update(cache, { data }) {
cache.modify({
fields: {
posts(existing = [], { toReference }) {
return [toReference(data.createPost), ...existing];
},
},
});
},
});
Critical: Always include __typename and id in optimistic responses. For deletes, use cache.evict() + cache.gc(). For simple cases, refetchQueries is fine.
See examples/core.md Pattern 3 for create, update, and delete mutation examples.
Pattern 4: Cache Type Policies
Type policies control how Apollo normalizes and retrieves cached data. This is where you configure cache identifiers, computed fields, pagination merging, and local state.
typePolicies: {
User: {
keyFields: ["id"],
fields: {
fullName: {
read(_, { readField }) {
return `${readField("firstName")} ${readField("lastName")}`;
},
},
},
},
Query: {
fields: {
isLoggedIn: { read() { return isLoggedInVar(); } },
},
},
}
Key patterns: keyFields for identification, merge for pagination, read for computed/local fields, keyArgs for separating cache entries per filter.
See examples/core.md Pattern 1 and examples/pagination.md for type policy examples.
Pattern 5: Pagination with fetchMore
Two approaches: Relay-style (cursor-based, use relayStylePagination) and offset-based (custom merge/read functions). Both require type policies for merging.
const { data, fetchMore } = useQuery(GET_USERS_CONNECTION, {
variables: { first: PAGE_SIZE },
});
const loadMore = () =>
fetchMore({
variables: { after: data.usersConnection.pageInfo.endCursor },
});
Key requirement: keyArgs must be set to separate cache entries per filter. Without it, different filtered queries overwrite each other.
See examples/pagination.md for infinite scroll with IntersectionObserver and custom offset pagination type policies.
Pattern 6: Fragment Colocation
Colocate data requirements with components using fragments. Parent queries include child fragments, so component changes don't require updating parent queries.
const USER_CARD_FRAGMENT = gql`
fragment UserCard on User {
id
name
email
avatar
}
`;
// Parent query includes child fragment
const GET_USERS = gql`
query GetUsers {
users {
...UserCard
}
}
${UserCard.fragments.user}
`;
See examples/fragments.md for fragment composition and examples/core.md Pattern 2 for fragments in queries.
Pattern 7: Subscriptions for Real-Time Data
Requires split link configuration: WebSocket for subscriptions, HTTP for queries/mutations. Use graphql-ws (not the deprecated subscriptions-transport-ws).
const splitLink = split(
({ query }) => {
const def = getMainDefinition(query);
return (
def.kind === "OperationDefinition" && def.operation === "subscription"
);
},
wsLink,
httpLink,
);
Important: Only create wsLink on the client side (typeof window !== "undefined"). Update cache in onData callback.
See examples/subscriptions.md for complete WebSocket setup and useSubscription with cache updates.
Pattern 8: Local State with Reactive Variables
Use makeVar for simple client-side state that integrates with Apollo's reactivity system. Suitable for theme, auth status, cart items - not complex state.
const cartItemsVar = makeVar<string[]>([]);
const addToCart = (id: string) => cartItemsVar([...cartItemsVar(), id]);
// Component reacts automatically
const cartItems = useReactiveVar(cartItemsVar);
When to use reactive vars vs external state management: Reactive vars for simple Apollo-integrated state. For complex non-GraphQL state, use your client state management solution.
Pattern 9: Suspense Hooks (v3.9+)
Four Suspense-enabled hooks for different loading patterns:
| Hook | Trigger | Use Case |
|---|---|---|
useSuspenseQuery |
Component mount | Standard data loading |
useLoadableQuery |
User interaction | Hover/click prefetch |
useBackgroundQuery |
Parent mount | Parent triggers, child reads |
createQueryPreloader |
Route transition | Router loader integration |
Key difference from useQuery: No loading state - component suspends instead. Errors throw to Error Boundary.
See examples/suspense.md for complete examples of all four patterns.
Pattern 10: useFragment for Data Masking (v3.8+)
Read fragment data directly from cache with automatic updates. Useful for components that only need a subset of cached entity data.
const { data: user, complete } = useFragment({
fragment: USER_CARD_FRAGMENT,
from: userRef,
});
if (!complete) return <Skeleton />;
Why useful: Reads directly from cache without additional queries, complete flag indicates if all fragment fields are available.
</patterns>
<version_migration>
Apollo Client v4 Migration Notes
Apollo Client v4 (released September 2025, latest v4.1.6) introduces significant breaking changes. A codemod handles most mechanical changes: npx @apollo/client-codemod-migrate-3-to-4
Breaking Changes Summary
| Change | v3 | v4 |
|---|---|---|
| React hook imports | @apollo/client |
@apollo/client/react |
Client uri option |
Allowed directly | Must use explicit HttpLink |
name/version |
Top-level on client | clientAwareness: { name, version } |
notifyOnNetworkStatusChange |
Default false |
Default true |
| Error classes | ApolloError |
CombinedGraphQLErrors, ServerError, ServerParseError |
| Observable library | zen-observable |
rxjs (peer dependency) |
| Link creation | createHttpLink() |
new HttpLink() (class-based) |
from()/concat()/split() |
Standalone functions | ApolloLink.from() static methods |
connectToDevTools |
Client option | Replaced by devtools: { enabled: true } |
| Local resolvers | resolvers on client |
Explicit LocalState class |
New: dataState Property (v4)
const { data, dataState } = useQuery(GET_USER);
// dataState: "empty" | "partial" | "streaming" | "complete"
if (dataState === "complete") {
// TypeScript knows data is fully populated
}
New: Error Type Guards (v4)
import { CombinedGraphQLErrors, ServerError } from "@apollo/client";
if (CombinedGraphQLErrors.is(error)) {
error.errors.forEach(({ message }) => console.error(message));
}
if (ServerError.is(error)) {
console.error(`Server responded with ${error.statusCode}`);
}
See Apollo Client 4 Migration Guide for complete details.
</version_migration>
<red_flags>
RED FLAGS
High Priority Issues:
- Manual GraphQL type definitions - Use GraphQL Codegen; manual types drift from schema causing runtime errors
- Missing
__typenamein optimistic responses - Cache normalization fails silently - Missing
idin query responses - Apollo cannot normalize data without identifiers - Missing
keyArgsin paginated type policies - Different filters overwrite each other in cache - (v4) Importing React hooks from
@apollo/client- Must use@apollo/client/reactin v4 - (v4) Using
urioption directly on ApolloClient - Must use explicitHttpLinkin v4
Medium Priority Issues:
- Not using
errorPolicy: "all"- Partial data is often better UX than complete failure refetchQueriesfor simple updates - Direct cache updates withcache.modifyare more efficientnetwork-onlyfor all queries -cache-and-networkprovides better UX (stale-while-revalidate)- Not typing
useQuery/useMutationgenerics - Loses type safety benefits - Missing loading/error state handling - Causes crashes when data is undefined and poor UX
Common Mistakes:
- Forgetting to run
graphql-codegenafter schema changes - Not including all required fields in optimistic responses (every field the mutation returns must be present)
- Using
cache.writeQuerywhencache.modifyis more appropriate (writeQuery replaces entire query result) - Mixing up
updatecallback (for cache updates) withonCompletedcallback (for side effects like navigation) - Not using
notifyOnNetworkStatusChangewhen showing refetch/fetchMore loading states
Gotchas & Edge Cases:
fetchMorepagination requires type policy merge functions - without them, new data replaces oldcache.evictmust be followed bycache.gc()to clean up orphaned referencesreadFieldin type policies is safer than direct property access (handles References)- Optimistic responses are discarded automatically on error - no manual rollback needed
refetchQueriesruns afterupdatecallback, not beforepollInterval: 0disables polling; omit the option entirely for no polling- Type policies with
keyFields: falseembed objects in parent (no separate cache entry) - Subscriptions require separate WebSocket link with
split- queries/mutations stay on HTTP useSuspenseQueryhas noloadingstate - it suspends; errors throw to Error BoundaryqueryReffromuseLoadableQuerymust be passed touseReadQueryinside a Suspense boundarycreateQueryPreloadermust be called outside the React tree (e.g., router loaders)- (v4)
notifyOnNetworkStatusChangedefaults totrue- may cause unexpected re-renders - (v4)
rxjsis a required peer dependency - must install explicitly - (v4)
ApolloErrorclass removed - useCombinedGraphQLErrors.is()andServerError.is()for type-checking - (v4)
from(),concat(),split()are static methods onApolloLink, not standalone functions - (v4)
createHttpLink()removed - usenew HttpLink()constructor instead - (v4)
useMutationtypes now enforce required variables at the call site
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
(You MUST use GraphQL Codegen for type generation - NEVER write manual TypeScript types for GraphQL)
(You MUST include __typename and id in all optimistic responses for cache normalization)
(You MUST configure type policies with appropriate keyFields for every entity type)
(You MUST use named constants for ALL timeout, retry, and polling values - NO magic numbers)
(For v4: You MUST import React hooks from @apollo/client/react - NOT from @apollo/client)
Failure to follow these rules will cause cache inconsistencies, type drift, and production bugs.
</critical_reminders>