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.
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
1. What is the primary purpose of ApolloProvider?
2. How does InMemoryCache normalize data by default?
3. What happens if a mutation response is missing the id and __typename fields for the modified entity?
4. Which hook is used to execute a GraphQL query and get loading/error/data state in a React component?
5. What tool would you use to inspect the normalized cache and watched queries during development?
Was this page helpful?
You May Also Like
GraphQL Code Generation
Understand how GraphQL Code Generator produces type-safe TypeScript types, hooks, and resolvers from your schema and operations.
Testing GraphQL APIs
Learn strategies for unit testing resolvers, integration testing schemas, and mocking GraphQL clients in tests.
GraphQL Quick Reference
A condensed cheat sheet of core GraphQL syntax, type system rules, and common patterns for fast lookup.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics