From gql
Apollo Client cache updates for mutations. Use when implementing mutations that should update the UI without refetching queries.
How this skill is triggered — by the user, by Claude, or both
Slash command
/gql:apollo-optimistic-updatesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use `cache.modify` in mutation `update` callbacks instead of `refetchQueries: 'active'` for faster, more efficient UI updates.
Use cache.modify in mutation update callbacks instead of refetchQueries: 'active' for faster, more efficient UI updates.
Update specific fields on cached entities directly:
const [mutate] = useMutation(MY_MUTATION, {
onCompleted: () => { /* cleanup */ },
onError: () => { /* handle error */ },
});
// Pass update in the mutation call to capture current values
mutate({
variables: { id, newValue },
update(cache, { data }) {
if (!data?.myMutation?.success) return;
cache.modify({
id: cache.identify({ __typename: 'MyType', id }),
fields: {
myField() {
return newValue;
},
},
});
},
});
update at call site, not hook config - closures in hook config capture stale valuescache.identify to get the cache key for an entity__typename in returned objects for new nested datamutate({
variables: { caseFileId, isRelevant, reason },
update(cache, { data }) {
if (!data?.case?.overrideRelevance?.success) return;
cache.modify({
id: cache.identify({ __typename: 'CaseFile', id: caseFileId }),
fields: {
relevanceOverride() {
return {
__typename: 'RelevanceOverride',
isRelevant,
reason,
createdBy: null, // Server-only field, okay to omit
};
},
},
});
},
});
mutate({
variables: { id },
update(cache, { data }) {
if (!data?.removeItem?.success) return;
cache.modify({
id: cache.identify({ __typename: 'Parent', id: parentId }),
fields: {
item() {
return null;
},
},
});
},
});
import type { Reference } from '@apollo/client/cache';
mutate({
variables: { parentId, newItem },
update(cache, { data }) {
if (!data?.createItem) return;
cache.modify({
id: cache.identify({ __typename: 'Parent', id: parentId }),
fields: {
items(existing: readonly Reference[] = []) {
const newRef = cache.writeFragment({
data: data.createItem,
fragment: gql`
fragment NewItem on Item {
id
name
}
`,
});
return [...existing, newRef];
},
},
});
},
});
import type { Reference, ModifierDetails } from '@apollo/client/cache';
mutate({
variables: { itemId },
update(cache, { data }) {
if (!data?.removeItem?.success) return;
cache.modify({
id: cache.identify({ __typename: 'Parent', id: parentId }),
fields: {
items(existing: readonly Reference[] = [], { readField }: ModifierDetails) {
return existing.filter(
(ref) => readField('id', ref) !== itemId
);
},
},
});
},
});
For instant UI feedback before the mutation even starts:
const [pendingValue, setPendingValue] = useState<T | null>(null);
// Use pending value for display, fall back to server value
const displayValue = pendingValue ?? serverValue;
const handleMutate = () => {
setPendingValue(newValue); // Instant UI update
mutate({
variables: { newValue },
update(cache, { data }) {
// Cache update for other components
},
onCompleted: () => setPendingValue(null),
onError: () => setPendingValue(null),
});
};
Still appropriate when:
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub cheapsteak/cheapsteak-agent-plugins --plugin gql