Reputation: 5197
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
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.
Upvotes: 1
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
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'],
}
},
});
Upvotes: 1
Reputation: 5197
It looks like this is behavior as intended. The Apollo Client normalizes on id
.
Upvotes: 6