Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are my Apollo cache updates not reflected in my queries?

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:

Cache before mutation

And a query returns as expected:

Query before mutation

After the mutation is performed, the cache updates:

Cache after mutation

However, running the query again results in the stale data:

enter image description here

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.

like image 445
cubabit Avatar asked Sep 15 '25 11:09

cubabit


1 Answers

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.

like image 199
cubabit Avatar answered Sep 18 '25 09:09

cubabit