Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo duplicates first result to every node in array of edges

Tags:

I am working on a react app with react-apollo calling data through graphql when I check in browser network tab response it shows all elements of the array different but what I get or console.log() in my app then all elements of array same as the first element. I don't know how to fix please help

like image 528
Bhaumik Gandhi Avatar asked Feb 17 '18 10:02

Bhaumik Gandhi


People also ask

What are the key args in Apollo GraphQL for?

keyArgs function (advanced) This function takes the field's arguments and other context as parameters, and it can return any string to use as the storage key (or a dynamically-generated keyArgs array). This is for advanced use cases. For details, see FieldPolicy API reference.

What is the default fetch policy Apollo?

A fetch policy defines how Apollo Client uses the cache for a particular query. The default policy is cache-first , which means Apollo Client checks the cache to see if the result is present before making a network request. If the result is present, no network request occurs.

What is Apollo InMemoryCache?

Apollo Client's InMemoryCache stores data as a flat lookup table of objects that can reference each other. These objects correspond to the objects that are returned by your GraphQL queries.

How do you persist the Apollo cache?

Persisting the cache To get started, pass your cache and a storage provider to persistCache . By default, the contents of your cache are immediately restored asynchronously, and they're persisted on every write to the cache with a short configurable debounce interval.


1 Answers

The reason this happens is because the items in your array get "normalized" to the same values in the Apollo cache. AKA, they look the same to Apollo. This usually happens because they share the same Symbol(id).

If you print out your Apollo response object, you'll notice that each of the objects have Symbol(id) which is used by Apollo cache. Your array items probably have the same Symbol(id) which causes them to repeat. Why does this happen?

By default, Apollo cache runs this function for normalization.

export function defaultDataIdFromObject(result: any): string | null {
  if (result.__typename) {
    if (result.id !== undefined) {
      return `${result.__typename}:${result.id}`;
    }
    if (result._id !== undefined) {
      return `${result.__typename}:${result._id}`;
    }
  }
  return null;
}

Your array item properties cause multiple items to return the same data id. In my case, multiple items had _id = null which caused all of these items to be repeated. When this function returns null the docs say

InMemoryCache will fall back to the path to the object in the query, such as ROOT_QUERY.allPeople.0 for the first record returned on the allPeople root query.

This is the behavior we actually want when our array items don't work well with defaultDataIdFromObject.

Therefore the solution is to manually configure these unique identifiers with the dataIdFromObject option passed to the InMemoryCache constructor within your ApolloClient. The following worked for me as all my objects use _id and had __typename.

const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache({
    dataIdFromObject: o => (o._id ? `${o.__typename}:${o._id}`: null),
  })
});
like image 176
Simon Avatar answered Sep 18 '22 21:09

Simon