I am trying to use Apollo cache for local state management to store the state of a form so it can be returned to without clearing.
I am experiencing a problem where the cache is being updated but subsequent queries to the cache are returning stale data. I have experienced this problem in React components using the useQuery
hook, and also in Apollo DevTools which I will use to demonstrate it below:
I have this mutation and query set in my resolvers (I am using Typescript):
const resolvers = {
Mutation: {
storeLetterDraft: (_root, args: { type: string, details: LetterSending }, { client, getCacheKey }) => {
const id = getCacheKey({
__typename: "LetterDraft",
id: args.type,
});
const data = { ...args.details };
client.writeFragment({
data,
id,
fragment: LETTER_SENDING_FRAGMENT,
});
},
},
Query: {
letterDraft: (_root, args: { type: string }, { client, getCacheKey }) => {
// I HAVE TRIED A DEBUGGER STATEMENT HERE
const id = getCacheKey({
__typename: "LetterDraft",
id: args.type,
});
return client.readFragment({
id,
fragment: LETTER_SENDING_FRAGMENT,
});
},
},
}
My fragment is:
export const LETTER_SENDING_FRAGMENT = gql`
fragment DraftLetterSending on LetterDraft {
date
firstName
lastName
addressLine1
addressLine2
addressTown
addressCounty
addressPostcode
}
`;
I am initialising my cache with:
cache.writeData({
data: {
letterDrafts: [{
__typename: "LetterDraft",
id: "CREATE",
addressCounty: "Northamptonshire",
addressLine1: "1 Watkin Terrace",
addressLine2: "",
addressPostcode: "NN1 3ER",
addressTown: "Northampton",
date: "2019-11-01",
firstName: "d",
lastName: "d",
}],
},
});
My mutation looks like:
export const storeCreateLetterSendingMutation = gql`
mutation StoreCreateLetterSending($details: LetterSending!) {
storeLetterDraft(type: "CREATE", details: $details) @client
}
`;
Before mutation, the cache in Apollo DevTools looks as expected:
And a query returns as expected:
After the mutation is performed, the cache updates:
However, running the query again results in the stale data:
Interestingly if I put a debugger statement in the part above (I HAVE TRIED A DEBUGGER STATEMENT HERE
), then it seems the query resolver is run the first time, but not the second time, so it appears the query is being cached - even though it is the cache I am updating! Therefore I think the issue is with the query not running the resolver subsequently.
I had missed this from the documentation (there are various places on the Apollo website detailing the local cache and @client.
https://www.apollographql.com/docs/react/essentials/local-state/#forcing-resolvers-with-clientalways-true
While leveraging the cache for both local and remote results can be super helpful in a lot of cases, it's not always the best fit. We might want to use a local resolver to calculate a dynamic value that needs to be refreshed on every request, while at the same time continue to use the cache for the network based parts of our query. To support this use case, Apollo Client's @client directive accepts an always argument, that when set to true will ensure that the associated local resolver is run on every request.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With