useQuery makes request instead taking data from cache

Hello, great question! This is one of the trickier nuances of the Apollo Client cache that I’m hoping to better clarify in the docs soon. To resolve your issue we can use cache redirects, which are documented here.

By default, the cache has no way to know that getCart should return the same Cart that was previously cached by cartLinesAddWithoutCart. To Apollo Client, these are two GraphQL operations that might have absolutely nothing to do with each other.

But! We can tell getCart how to check the cache for an existing Cart object so that it doesn’t need to hit the network. To do that, we can define a custom read function for Query.cart in our InMemoryCache constructor, like so:

const client = new ApolloClient({
  link,
  cache: new InMemoryCache({
      typePolicies: {
        Query: {
          fields: {
            cart: {
              read(cart, { args, toReference }) {
                if (!cart) {
                  // No cart associated with this query, but there still
                  // might be one elsewhere in the cache. Check!
                  return toReference({
                    __typename: 'Cart',
                    id: args.id,
                  });
                } else {
                  // There's already a cart associated with this query,
                  // so return it
                  return cart;
                }
              }
            }
          }
        }
    }
  })
});

With this read function, whenever Query.cart is queried, if that field doesn’t already have an associated cart object in the cache, it generates a reference to a Cart object that might be somewhere else in the cache (specifically, returned by cartLinesAddWithoutCart).

That reference consists of the Cart typename, plus the id that was provided to the original query as an argument. If the cache does indeed contain a Cart object that corresponds to that reference, it’s returned! And otherwise, Apollo Client knows there is no Cart with that id in the cache, so a network request is necessary (assuming you have a cache-first fetch policy).

I forked your sandbox and applied this read function here. Clicking Create cart and add now successfully updates the Cart component, even though the fetch policy is set to cache-only. The cart is being successfully fetched from the cache.

1 Like