natlee75
natlee75

Reputation: 5197

Apollo Client replaces an array of objects with the same id and different values with an array of copies of the first object

Our GraphQL server responds to a query with data that includes an array of objects each of which shares the same id and different values for a different key. For instance, we might have an array that looks like:

[
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 6 },
  { id: 123, name: 'foo', type: 'bar', cost: 7 },
  { id: 123, name: 'foo', type: 'bar', cost: 8 }
]

We can see in the Network tab that the response from the server has the correct data in it. However, by the time it goes through processing by the Apollo Client module the array has been transformed into something that might look like this:

[
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 }
]

Essentially what we're seeing is that if all of the objects in an array share the same value for id then all objects in the array become copies of the first object in the array.

Is this the intended behavior of Apollo Client? We thought maybe it had something to do with incorrect caching, but we were also wondering if maybe Apollo Client assumed that subsequent array members with the same id were the same object.

Upvotes: 7

Views: 3171

Answers (4)

foxiris
foxiris

Reputation: 3378

I have the same issue. My solution is to set fetchPolicy: "no-cache" just for this single API so you don't have to change the InMemoryCache. Note that setting fetchPolicy to network-only is insufficient because it still uses the cache.

fetchPolicy document

Upvotes: 1

Urbana 28
Urbana 28

Reputation: 1

It works for me: const cache: InMemoryCache = new InMemoryCache({ dataIdFromObject: o => false )};

previous answer solves this problem too! Also you can change the key name(for example id => itemId) on back-end side and there won't be any issue!

Upvotes: 0

Aurelio
Aurelio

Reputation: 25802

As the other answer suggests this happens because Apollo normalises by ID. There's a very extensive article on the official blog that explains the rationale of it, along with the underlying mechanisms.

In short, as seen by Apollo's cache, your array of objects contains 4 instances of the same Object (id 123). Same ID, same object.

This is a fair assumption on Apollo's side, but not so much in your case. You have to explicitly tell Apollo that these are indeed 4 different items that should be treated differently.

In the past we used dataIdFromObject, and you can see an example here.

Today, you would use typePolicies and keyfields:

const cache = new InMemoryCache({
  typePolicies: {
    YourItem: {
      // Combine the fields that make your item unique
      keyFields: ['id', 'cost'],
    }
  },
});

Docs

Upvotes: 1

natlee75
natlee75

Reputation: 5197

It looks like this is behavior as intended. The Apollo Client normalizes on id.

Upvotes: 6

Related Questions