Apollo Client is a comprehensive state management library for JavaScript that enables you to manage both local and remote data with GraphQL. Version 4.x brings improved caching, better TypeScript support, and React 19 compatibility. Choose the integration guide that matches your application setup: - **[Client-Side Apps](https://github.com/apollographql/skills/blob/main/skills/apollo-client/references/integration-client.md)** - For client-side React applications without SSR (Vite, Create React
import { gql } from "@apollo/client"; import { useQuery } from "@apollo/client/react"; const GET_USER = gql` query GetUser($id: ID!) { user(id: $id) { id name } } `; function UserProfile({ userId }: { userId: string }) { const { loading, error, data, dataState } = useQuery(GET_USER, { variables: { id: userId }, }); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error.message}</p>; // TypeScript: dataState === "ready" provides better type narrowing than just checking data return <div>{data.user.name}</div>; } `### Basic Mutation` import { gql } from "@apollo/client"; import { useMutation } from "@apollo/client/react"; const CREATE_USER = gql` mutation CreateUser($input: CreateUserInput!) { createUser(input: $input) { id name } } `; function CreateUserForm() { const [createUser, { loading, error }] = useMutation(CREATE_USER); const handleSubmit = async (name: string) => { await createUser({ variables: { input: { name } } }); }; return <button onClick={() => handleSubmit("John")}>Create User</button>; } `### Suspense Query` import { Suspense } from "react"; import { useSuspenseQuery } from "@apollo/client/react"; function UserProfile({ userId }: { userId: string }) { const { data } = useSuspenseQuery(GET_USER, { variables: { id: userId }, }); return <div>{data.user.name}</div>; } function App() { return ( <Suspense fallback={<p>Loading user...</p>}> <UserProfile userId="1" /> </Suspense> ); }
useFragment or useSuspenseFragment in all non-page-components. Use @defer to allow slow fields below the fold to stream in later and avoid blocking the page load.loading and error states in UI when using non-suspenseful hooks (useQuery, useLazyQuery). When using Suspense hooks (useSuspenseQuery, useBackgroundQuery), React handles this through <Suspense> boundaries and error boundaries.fetchPolicy to control cache behavior per queryrefetchQueries sparingly (prefer letting the cache update automatically)keyFields for types without id fieldkeyFields: false for types that don't include an identifier and are meant to group related fields under the parenttypePolicies for pagination and computed fieldsfetchPolicy per use case@defer for incremental delivery of deferred query parts, and @stream for streaming list fields (@stream available in Apollo Client 4.1+)useSuspenseQuery, useBackgroundQuery) in modern applications for better loading state handling and code simplicityApolloProvideruseSuspenseQuery, useBackgroundQuery) in modern applications for better DXcache-first for read-heavy data, network-only for real-time data