Skip to content
Back to skills

Graphql Apollo Client

ASecurity

Build React apps with Apollo Client - queries, mutations, cache, and subscriptions

  • 666 stars
  • 0 votes
  • 0 copies
  • 6 views
  • Added February 8, 2026
developmenttypescriptreactnode

Works with

  • cursor
  • cli

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add majiayu000/claude-skill-registry --skill graphql-apollo-client --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Graphql Apollo Client?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Graphql Apollo Client
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-graphql-apollo-client/badge)](https://www.skillsdirectory.com/skills/majiayu000-graphql-apollo-client)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: graphql-apollo-client
description: Build React apps with Apollo Client - queries, mutations, cache, and subscriptions
sasmp_version: "1.3.0"
bonded_agent: 05-graphql-apollo-client
bond_type: PRIMARY_BOND
version: "2.0.0"
complexity: intermediate
estimated_time: "4-6 hours"
prerequisites: ["graphql-fundamentals"]
---

# Apollo Client Skill

> Master GraphQL in React applications

## Overview

Learn to integrate Apollo Client with React, including hooks, cache management, optimistic updates, and real-time subscriptions.

---

## Quick Reference

| Hook | Purpose | Returns |
|------|---------|---------|
| `useQuery` | Fetch data | `{ data, loading, error, refetch }` |
| `useMutation` | Modify data | `[mutate, { data, loading, error }]` |
| `useSubscription` | Real-time | `{ data, loading, error }` |
| `useLazyQuery` | On-demand fetch | `[execute, { data, loading }]` |

---

## Core Patterns

### 1. Client Setup

```typescript
import {
  ApolloClient,
  InMemoryCache,
  ApolloProvider,
  createHttpLink,
  from
} from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
import { onError } from '@apollo/client/link/error';

// HTTP connection
const httpLink = createHttpLink({
  uri: 'http://localhost:4000/graphql',
  credentials: 'include',
});

// Auth header
const authLink = setContext((_, { headers }) => ({
  headers: {
    ...headers,
    authorization: localStorage.getItem('token')
      ? `Bearer ${localStorage.getItem('token')}`
      : '',
  },
}));

// Error handling
const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(({ message, extensions }) => {
      if (extensions?.code === 'UNAUTHENTICATED') {
        window.location.href = '/login';
      }
    });
  }
});

// Cache with type policies
const cache = new InMemoryCache({
  typePolicies: {
    User: { keyFields: ['id'] },
    Query: {
      fields: {
        users: {
          keyArgs: ['filter'],
          merge(existing, incoming, { args }) {
            if (!args?.after) return incoming;
            return {
              ...incoming,
              edges: [...(existing?.edges || []), ...incoming.edges],
            };
          },
        },
      },
    },
  },
});

// Client
const client = new ApolloClient({
  link: from([errorLink, authLink, httpLink]),
  cache,
});

// Provider
function App() {
  return (
    <ApolloProvider client={client}>
      <Router />
    </ApolloProvider>
  );
}
```

### 2. Queries

```typescript
import { gql, useQuery } from '@apollo/client';

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

function UserProfile({ userId }) {
  const { data, loading, error, refetch } = useQuery(GET_USER, {
    variables: { id: userId },
    // Options
    fetchPolicy: 'cache-and-network',
    pollInterval: 60000, // Refetch every minute
    skip: !userId,       // Skip if no userId
  });

  if (loading) return <Spinner />;
  if (error) return <Error onRetry={refetch} />;

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

// Pagination
function UserList() {
  const { data, fetchMore, networkStatus } = useQuery(GET_USERS, {
    variables: { first: 10 },
    notifyOnNetworkStatusChange: true,
  });

  const loadMore = () => {
    fetchMore({
      variables: { after: data.users.pageInfo.endCursor },
    });
  };

  return (
    <>
      {data?.users.edges.map(({ node }) => (
        <UserCard key={node.id} user={node} />
      ))}
      {data?.users.pageInfo.hasNextPage && (
        <button onClick={loadMore}>Load More</button>
      )}
    </>
  );
}
```

### 3. Mutations

```typescript
const CREATE_USER = gql`
  mutation CreateUser($input: CreateUserInput!) {
    createUser(input: $input) {
      user { id name email }
      errors { field message }
    }
  }
`;

function CreateUserForm() {
  const [createUser, { loading }] = useMutation(CREATE_USER, {
    // Update cache after success
    update(cache, { data }) {
      if (!data?.createUser.user) return;

      cache.modify({
        fields: {
          users(existing = { edges: [] }) {
            const newRef = cache.writeFragment({
              data: data.createUser.user,
              fragment: gql`fragment NewUser on User { id name email }`,
            });
            return {
              ...existing,
              edges: [{ node: newRef }, ...existing.edges],
            };
          },
        },
      });
    },

    // Optimistic response
    optimisticResponse: (vars) => ({
      createUser: {
        __typename: 'CreateUserPayload',
        user: {
          __typename: 'User',
          id: 'temp-' + Date.now(),
          ...vars.input,
        },
        errors: [],
      },
    }),
  });

  const handleSubmit = async (input) => {
    const { data } = await createUser({ variables: { input } });
    if (data?.createUser.errors.length) {
      // Handle validation errors
    }
  };

  return <Form onSubmit={handleSubmit} loading={loading} />;
}
```

### 4. Optimistic Updates

```typescript
// Delete
const [deleteUser] = useMutation(DELETE_USER, {
  optimisticResponse: {
    deleteUser: { success: true, id: userId },
  },
  update(cache, { data }) {
    cache.evict({ id: cache.identify({ __typename: 'User', id: userId }) });
    cache.gc();
  },
});

// Toggle
const [toggleLike] = useMutation(TOGGLE_LIKE, {
  optimisticResponse: {
    toggleLike: {
      __typename: 'Post',
      id: post.id,
      isLiked: !post.isLiked,
      likeCount: post.isLiked ? post.likeCount - 1 : post.likeCount + 1,
    },
  },
});
```

### 5. Subscriptions

```typescript
import { useSubscription } from '@apollo/client';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { createClient } from 'graphql-ws';
import { split } from '@apollo/client';
import { getMainDefinition } from '@apollo/client/utilities';

// WebSocket link
const wsLink = new GraphQLWsLink(
  createClient({
    url: 'ws://localhost:4000/graphql',
    connectionParams: () => ({
      authToken: localStorage.getItem('token'),
    }),
  })
);

// Split between HTTP and WS
const splitLink = split(
  ({ query }) => {
    const def = getMainDefinition(query);
    return def.kind === 'OperationDefinition' && def.operation === 'subscription';
  },
  wsLink,
  httpLink,
);

// Usage
const MESSAGE_SUB = gql`
  subscription OnMessage($channelId: ID!) {
    messageSent(channelId: $channelId) {
      id
      content
      sender { name }
    }
  }
`;

function Chat({ channelId }) {
  const { data } = useSubscription(MESSAGE_SUB, {
    variables: { channelId },
  });

  // New message in data?.messageSent
}
```

---

## Troubleshooting

| Issue | Cause | Solution |
|-------|-------|----------|
| Stale data | Cache not updated | Add update function |
| Duplicates | Missing keyFields | Configure typePolicies |
| Refetch loop | Variables object recreated | useMemo variables |
| No subscription | Missing split link | Add wsLink |

### Debug

```typescript
// Cache inspection
console.log(client.cache.extract());

// Apollo DevTools
// Install browser extension

// Logging link
import { ApolloLink } from '@apollo/client';

const logLink = new ApolloLink((operation, forward) => {
  console.log('Request:', operation.operationName);
  return forward(operation);
});
```

---

## Usage

```
Skill("graphql-apollo-client")
```

## Related Skills
- `graphql-fundamentals` - Query syntax
- `graphql-apollo-server` - Server integration
- `graphql-codegen` - Type generation

## Related Agent
- `05-graphql-apollo-client` - For detailed guidance

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.