100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
GraphQL

Apollo Client Basics

Learn how Apollo Client manages GraphQL queries, mutations, and the normalized cache in front-end applications.

Tooling & PracticeIntermediate10 min readJul 10, 2026
Analogies

What Apollo Client Does

Apollo Client is a state management library that fetches, caches, and updates data from a GraphQL API while keeping your UI in sync. Instead of manually tracking loading and error states with fetch calls, you declare a query with the useQuery hook and Apollo handles the request lifecycle, retries, and re-rendering when cached data changes.

🏏

Cricket analogy: Like a team analyst who continuously tracks a batsman's strike rate and updates the scoreboard automatically rather than making commentators recalculate it after every ball, Apollo keeps UI state synced without manual polling.

Setting Up ApolloClient and ApolloProvider

Every Apollo Client app starts by instantiating an ApolloClient object with a uri pointing to the GraphQL endpoint and a cache instance, typically InMemoryCache. Wrapping your app in ApolloProvider makes this client instance available to every component via React context, so any component can call useQuery, useMutation, or useSubscription without threading props manually.

🏏

Cricket analogy: Like installing a single Hawk-Eye ball-tracking rig at the stadium that every broadcaster taps into rather than each camera crew building their own, ApolloProvider supplies one shared client to the whole component tree.

javascript
import { ApolloClient, InMemoryCache, ApolloProvider, gql, useQuery } from '@apollo/client';

const client = new ApolloClient({
  uri: 'https://api.example.com/graphql',
  cache: new InMemoryCache(),
});

function App() {
  return (
    <ApolloProvider client={client}>
      <BookList />
    </ApolloProvider>
  );
}

const GET_BOOKS = gql`
  query GetBooks {
    books {
      id
      title
      author
    }
  }
`;

function BookList() {
  const { loading, error, data } = useQuery(GET_BOOKS);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <ul>
      {data.books.map((book) => (
        <li key={book.id}>{book.title} by {book.author}</li>
      ))}
    </ul>
  );
}

The Normalized Cache and Mutations

InMemoryCache normalizes response data by flattening objects into a lookup table keyed by __typename:id, so the same entity fetched through two different queries is stored once and updated everywhere it's referenced. When you run a mutation with useMutation, Apollo can automatically update the cache if the mutation response includes the same fields, or you can manually adjust it using update functions, refetchQueries, or cache field policies.

🏏

Cricket analogy: Like a single player database that both the batting and bowling scorecards reference rather than duplicating stats for Virat Kohli in two places, normalized cache avoids inconsistent copies of the same entity.

If your mutation response doesn't return the id and __typename fields for the modified entity, Apollo cannot automatically normalize and merge the update into the cache — you'll need to specify an update function or set refetchQueries explicitly, otherwise the UI can silently show stale data.

Use Apollo Client DevTools (browser extension) to inspect the normalized cache contents, watched queries, and mutation history — invaluable for debugging why a component isn't re-rendering after a mutation.

  • ApolloClient combines a network layer with InMemoryCache to manage GraphQL data on the client.
  • ApolloProvider uses React context to make one client instance available app-wide.
  • useQuery returns loading, error, and data states and automatically re-renders on cache changes.
  • useMutation executes writes and can update the cache automatically if the response includes id and __typename.
  • InMemoryCache normalizes entities by __typename:id so the same entity is stored once and shared across queries.
  • Manual cache updates require the update function, refetchQueries, or cache field policies for non-trivial mutations.
  • Apollo Client DevTools helps debug cache state and why components aren't reflecting fresh data.

Practice what you learned

Was this page helpful?

Topics covered

#GraphQL#GraphQLStudyNotes#WebDevelopment#ApolloClientBasics#Apollo#Client#Does#Setting#APIs#StudyNotes#SkillVeris