Why GraphQL
GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. A client describes the shape of the data it wants and receives exactly that — nothing more, nothing less — in a predictable structure.
Queries can follow references between resources, so data that a typical REST API would spread across several URLs arrives in a single request. Because the client controls what it fetches, applications stay fast and stable as screens evolve.
What Apollo Client adds
Apollo Client is a fully featured JavaScript GraphQL client. It sends queries and mutations, caches results in a normalized in-memory store, tracks loading and error states, and integrates with React, Angular and Vue. Its cache also doubles as a home for local state, kept in step with the server.
Install it alongside the reference graphql package:
npm install @apollo/client graphql
- @apollo/client
- Querying and mutating data, a normalized cache for local and remote data, subscriptions for real-time updates, error handling and retries, and links for customizing requests.
- graphql
- The reference implementation used to parse and validate queries. On the server it defines schemas and resolvers; on the client it parses the documents you send.
Connecting the client
Create one client for the application — pointing an HttpLink at your GraphQL endpoint and giving it a cache — then provide it to the component tree:
import { createRoot } from "react-dom/client";
import { ApolloClient, HttpLink, InMemoryCache } from "@apollo/client";
import { ApolloProvider } from "@apollo/client/react";
import App from "./App";
const client = new ApolloClient({
link: new HttpLink({ uri: "https://api.example.com/graphql" }),
cache: new InMemoryCache(),
});
createRoot(document.getElementById("root")).render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
);Version note
Since Apollo Client 4, React APIs such as
ApolloProvider,useQueryanduseMutationare imported from@apollo/client/react, and the endpoint is configured through a link rather than aurishortcut. Older projects on version 3 import everything from@apollo/client.
Reading data with useQuery
Define the query with gql. Its structure mirrors the data you expect back — one of GraphQL’s defining features:
import { gql } from "@apollo/client";
export const GET_USERS = gql\`
query GetUsers {
users {
id
name
email
}
}
\`;Arguments narrow the result. To fetch only the name and email of user 123, ask for exactly that:
query GetUser {
user(id: 123) {
name
email
}
}
The useQuery hook runs the query, re-renders as its state changes, and serves repeat requests from the cache:
import { useQuery } from "@apollo/client/react";
import { GET_USERS } from "./queries";
export default function UserList() {
const { loading, error, data } = useQuery(GET_USERS);
if (loading) return <p>Loading…</p>;
if (error) return <p role="alert">Couldn’t load users: {error.message}</p>;
return (
<ul>
{data.users.map((user) => (
<li key={user.id}>
{user.name} ({user.email})
</li>
))}
</ul>
);
}Keep reading — it’s free
The remaining 3 min of this story is for Dispatch subscribers. Subscribing takes one field, and the whole story opens right here.
Subscribe to read the rest
Free. One email when there’s something worth reading.
Originally published at Aviox Blogs engineering handbook.


