This chapter follows Typed operations with GraphQL Codegen.
The default cacheExchange stores operations by key. @urql/exchange-graphcache normalizes entities by __typename and id (or custom keys) so updating one mutation refreshes every query that referenced the same record.
Enable Graphcache
Replace cacheExchange with cacheExchange from @urql/exchange-graphcache:
import { cacheExchange } from "@urql/exchange-graphcache";import { createClient, fetchExchange } from "urql";
export const client = createClient({ url: "/graphql", exchanges: [cacheExchange({}), fetchExchange],});Pass schema (introspection JSON or codegen artifact) so Graphcache understands interfaces and unions when writing links.
Records and links
Graphcache maintains:
- Records — scalar fields keyed by entity ID (
Book:1) - Links — relations between records (
Query.books→ list ofBookrecords)
When a query returns { id, __typename, title }, later mutations can patch Book:1 and all list queries see the new title without refetching.
keys and non-ID entities
Types without a natural ID need custom keys:
cacheExchange({ keys: { SearchResult: () => null, // embedded, not normalized Product: (data) => data.sku as string, },});Returning null from keys embeds the object under its parent instead of a standalone record.
updates after mutations
Tell Graphcache how to merge mutation results:
cacheExchange({ updates: { Mutation: { createBook(result, _args, cache) { cache.updateQuery({ query: BooksDocument }, (data) => { if (!data) return data; return { ...data, books: [...data.books, result.createBook] }; }); }, }, },});Prefer cache.updateQuery and cache.writeFragment over manual cache inspection.
Optimistic updates
useMutation(CreateBookDocument, { optimistic: { createBook: { id: "temp-id", __typename: "Book", title: "Draft", }, },});Graphcache rolls back if the server errors. Match shape to the mutation selection set.
Resolvers and offline
resolvers on Graphcache can resolve fields locally when offline or while waiting for network—useful for read-through caches of computed fields. storage adapters persist the cache to IndexedDB for offline-first apps; replay queues mutations when connectivity returns.
Next: Evolving a GraphQL schema.
Check your understanding
Question 1 of 6
0 of 6 checked