Cache Exchange
Normalized caching with automatic dependency tracking and fine-grained updates.
Basic Usage
typescript
import { createClient, cacheExchange, httpExchange } from '@mearie/react'; // or @mearie/vue, @mearie/svelte, @mearie/solid
import { schema } from '$mearie';
export const client = createClient({
schema,
exchanges: [cacheExchange(), httpExchange({ url: 'https://api.example.com/graphql' })],
});How It Works
- Normalize - Breaks down responses into entities (e.g.,
User:123) - Store - Saves entities in a normalized map
- Track - Registers which queries depend on which entities
- Invalidate - Updates only affected queries when data changes
Configuration
Fetch Policy
Set default caching behavior:
typescript
export const client = createClient({
schema,
exchanges: [
cacheExchange({
fetchPolicy: 'cache-first', // Default for all operations
}),
httpExchange({ url: 'https://api.example.com/graphql' }),
],
});Available policies:
- cache-first (default) - Use cache if available, otherwise fetch
- cache-and-network - Return cached data immediately, then fetch and update
- network-only - Always fetch from network, update cache
- cache-only - Only use cache, throw error if not found
INFO
Mutations and subscriptions always use network-only fetch policy, regardless of the configured default.
You can override this per operation. See Per-Operation Fetch Policy.
Automatic Cache Updates
Cache automatically updates when mutations return data:
typescript
export const EditUser = ({ userId }: { userId: string }) => {
const [updateUser] = useMutation(
graphql(`
mutation UpdateUser($id: ID!, $name: String!) {
updateUser(id: $id, input: { name: $name }) {
id
name
}
}
`),
);
const handleSubmit = async (name: string) => {
await updateUser({ id: userId, name });
// Cache automatically updates User:${userId} with new name
// All components using this user re-render automatically
};
// ...
};Per-Operation Fetch Policy
Override the default fetch policy for specific queries:
typescript
export const UserProfile = ({ userId }: { userId: string }) => {
const { data } = useQuery(
graphql(`
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
`),
{ id: userId },
{ fetchPolicy: 'network-only' }, // Override default
);
return <h1>{data.user.name}</h1>;
};WARNING
Mutations and subscriptions always use network-only and cannot be overridden.
Progressive Enhancement
Cache is completely optional. Start without it:
typescript
export const client = createClient({
schema,
exchanges: [httpExchange({ url: 'https://api.example.com/graphql' })],
});Add caching later with one line - components automatically benefit:
typescript
export const client = createClient({
schema,
exchanges: [cacheExchange(), httpExchange({ url: 'https://api.example.com/graphql' })],
});Exchange Chain Placement
Place cacheExchange before httpExchange:
typescript
export const client = createClient({
schema,
exchanges: [
dedupExchange(),
retryExchange(),
cacheExchange(), // Before HTTP
httpExchange({ url: 'https://api.example.com/graphql' }),
],
});This ensures cache is checked before making network requests.
Next Steps
- Retry Exchange - Automatically retry failed requests
- Deduplication Exchange - Prevent duplicate requests
- Exchanges - Learn about the exchange system