Lingertje
Lingertje

Reputation: 236

How can I cache nested objects with Apollo Client?

I'm using the Contentful GraphQL API to fetch a collection of items, in this example football clubs.

query Clubs($limit: Int!, $skip: Int!) {
    clubCollection(limit: $limit, skip: $skip) {
        total
        items {
            name
            description
        }
    }
}

The structure of the response is:

clubCollection: {
  items: [{
    ... array of all the clubs
  }]
}

It looks like the Apollo InMemoryCache is only caching the full query in its ROOT_QUERY object. But not each individual club. The setup for the cache looks like this:

new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        clubCollection: concatContentfulPagination()
      },
    },
  },
})

Does anyone know how I can target the clubs in items so that I can cache each individual club?

EDIT: Thanks to the answer from @xadm I realised I did not need to extend the InMemoryCache like so:

new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        clubCollection: {
          items: { 
          
          },
          ...concatContentfulPagination()
        }
      },
    },
  },
})

But instead add it to the root of the typePolicies based on the type of the object, for me it is Club. When I added that it did work!

new InMemoryCache({
  typePolicies: {
    Club: {
      keyFields: ['name']
    },
    Query: {
      fields: {
        clubCollection: concatContentfulPagination()
      },
    },
  },
})

Upvotes: 4

Views: 5046

Answers (2)

xadm
xadm

Reputation: 8418

Items should have an id prop requested ... to be normalized - Apollo is normalizing cache GraphQL client

It's required to cache entries/types/subtypes properly.

https://graphql.org/learn/caching/

It, unique key can be id, _id or customized key per type using typePolicies - customizing-identifier-generation-by-type.

https://www.apollographql.com/docs/react/caching/cache-configuration/#default-identifier-generation

In this case (no queryable id prop inside items), you should check in API (docs/specs/schema or explore network response body - __typename prop of items object) the type of club items entries (probably Club) and customize cache policies like:

new InMemoryCache({
  typePolicies: {
    Club: {
      keyFields: ['name']
    },

... assuming name is unique.

Upvotes: 3

Rishabh Singh
Rishabh Singh

Reputation: 391

For this pupose you can use reactive variables. That way you can access clubs array anywhere in your code without rerunning query and perform any array operation on it. Visit this page for more info on it.

Upvotes: 0

Related Questions