Search

PythonReactSEOPDF
GitHub Skill

apollo-client

This skill should be used when writing or modifying GraphQL operations, hooks, or mutations using Apollo Client 3.10. It enforces best practices for optimistic responses, cache updates, and TypeScript type generation. Use this skill when creating new queries/mutations, reviewing Apollo code, or troubleshooting cache issues.

CodySwannGT☆ 1 Repository stars1 Repository forks

Installation

Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.

View source ↗Guides

Skill instructions

Apollo Client 3.10

Overview

This skill provides best practices for Apollo Client 3.10 in this codebase, ensuring consistent patterns for GraphQL operations, optimistic UI updates, cache management, and TypeScript type safety.

Quick Reference

Generator Commands

After modifying any operations.graphql file, run the appropriate generator:

bun run generate:types:dev        # Development environment
bun run generate:types:staging    # Staging environment
bun run generate:types:production # Production environment

Note: Replace bun with your project's package manager (npm, yarn, pnpm) as needed.

Import Pattern

All GraphQL types, hooks, and documents must come from generated types:

import {
  useGetPlayerQuery,
  useUpdatePlayerMutation,
  GetPlayerQuery,
  PlayerFragment,
  ListPlayersDocument,
} from "@/generated/graphql";

Core Rules

1. Only Use Generated Types

Import all GraphQL-related types from @/generated/graphql. Never define manual TypeScript types for GraphQL entities.

// CORRECT
import { PlayerFragment, useUpdatePlayerMutation } from "@/generated/graphql";

// INCORRECT - Never do this
type Player = { id: string; name: string };
2. Never Modify Generated Files

The generated/graphql.ts file is auto-generated by codegen. To change types:

  1. Edit the appropriate operations.graphql file in the feature directory
  2. Run bun run generate:types:dev
  3. Import the newly generated types
3. Always Run Generator After Schema Changes

After modifying any operations.graphql file, immediately run the generator before committing. Verify changes compile with bun run typecheck.

4. Always Include Optimistic Response

Every mutation must include an optimisticResponse for instant UI feedback:

const [updatePlayer] = useUpdatePlayerMutation({
  optimisticResponse: variables => ({
    __typename: "Mutation",
    updatePlayer: {
      __typename: "Player",
      id: variables.id,
      name: variables.input.name,
      updatedAt: new Date().toISOString(),
    },
  }),
});

Key requirements:

  • Always include __typename for every object in the response
  • Always include id for cache normalization
  • Use temporary IDs for new objects (e.g., crypto.randomUUID())
  • Include all fields that the mutation returns
5. Always Update Cache

Every mutation must handle cache updates using one of these strategies:

Automatic Updates - When mutation returns the full entity with id and __typename, Apollo updates automatically. No extra code needed.

cache.modify - For adding/removing items from lists:

const [addPlayer] = useAddPlayerMutation({
  optimisticResponse: {
    /* ... */
  },
  update(cache, { data }) {
    cache.modify({
      fields: {
        players(existingPlayers = [], { readField }) {
          const newRef = cache.writeFragment({
            data: data.addPlayer,
            fragment: PlayerFragmentDoc,
          });
          return [...existingPlayers, newRef];
        },
      },
    });
  },
});

refetchQueries - Fallback for complex scenarios:

const [complexMutation] = useComplexMutation({
  refetchQueries: ["ListPlayers"],
  awaitRefetchQueries: true,
});

Operations.graphql Structure

Fragment-First Pattern

Define fragments before queries/mutations that use them:

# 1. Fragments first
fragment PlayerFragment on Player {
  id
  knownName
  firstName
  lastName
  team {
    id
    name
  }
}

# 2. Queries second
query GetPlayer($id: ID!) {
  player(id: $id) {
    ...PlayerFragment
  }
}

# 3. Mutations last
mutation UpdatePlayer($id: ID!, $input: UpdatePlayerInput!) {
  updatePlayer(id: $id, input: $input) {
    ...PlayerFragment
  }
}
Include Required Fields

Mutations must return all fields needed for cache updates:

mutation AddPlayerToKanban($input: AddPlayerToKanbanInput!) {
  addPlayerToKanban(input: $input) {
    id # Required for cache normalization
    position
    notes
    kanbanPhaseId
    kanbanPhase {
      # Include related objects
      id
      name
    }
    createdAt
    updatedAt
  }
}

Query Best Practices

Fetch Policies
// Frequently changing data - balance speed and freshness
fetchPolicy: "cache-and-network";

// Stable reference data - prioritize cache
fetchPolicy: "cache-first";

// Always-fresh data - skip cache
fetchPolicy: "network-only";
Skip When Variables Undefined
const { data } = useGetPlayerQuery({
  variables: { id: playerId! },
  skip: !playerId,
});
Error Handling

Use onError callback instead of try/catch with console.log:

const [mutation] = useMutation(MUTATION, {
  onError: error => {
    setErrorState("Failed to update. Please try again.");
  },
});

Complete Mutation Pattern

Reference references/mutation-patterns.md for comprehensive examples of the complete mutation pattern including optimistic responses, cache updates, and error handling.

Validation Checklist

When writing or reviewing Apollo code, verify:

  • All types imported from @/generated/graphql
  • No manual type definitions for GraphQL entities
  • Every mutation has optimisticResponse
  • Every mutation has cache update strategy
  • __typename included in all optimistic response objects
  • id included in all optimistic response objects
  • Queries use appropriate fetchPolicy
  • Queries use skip when variables may be undefined
  • Error handling via onError callback
  • Generator was run after operations.graphql changes

Examples

Read the usage examples in the source repository.

View source ↗

Source history

Indexed on
2026-01-20
Index updated
2026-01-26
Branch
main

Index and sync dates describe this directory. View the source repository for code history.

GitHub ↗

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!