apollo-client: Wrong response when parsed by apollo
I call graphql to get a membership table layout with the following query:
query ($ids: [String]!, $countryCode: String!) {
flows(ids: $ids, countryCode: $countryCode) {
table {
id
title
blocks {
name
id
plans {
id
initial
level
media
name
recurring
recurring_period
trial_length
type
restrictions {
id
typeId
type
value
}
}
}
}
}
}
And when I look in the network tab I see this (which is correct): https://gist.github.com/charles-mathieus-jomedia/28ea24688c9163c364739a6e6b36bb1b TL;DR
flow: {
tables: [
{
blocks: [
{ id: 'audiobooks', name: 'block1' },
{ id: 'all', name: 'block2' }
{ id: 'family', name: 'block3' }
]
},
{
blocks: [
{ id: 'audiobooks', name: 'block4' },
{ id: 'all', name: 'block5' }
{ id: 'combo', name: 'block6' }
]
},
]
}
Intended outcome:
I get the right blocks when I remove the ids from the block in the query: https://gist.github.com/charles-mathieus-jomedia/05c3de397de2ddcfadf06f5914035337 TL;DR
flow: {
tables: [
{
blocks: [
{ id: 'audiobooks', name: 'block1' },
{ id: 'all', name: 'block2' }
{ id: 'family', name: 'block3' }
]
},
{
blocks: [
{ id: 'audiobooks', name: 'block4' },
{ id: 'all', name: 'block5' }
{ id: 'combo', name: 'block6' }
]
},
]
}
Actual outcome:
When I leave the ids, I get the wrong blocks: https://gist.github.com/charles-mathieus-jomedia/2d1e61404a944fb9a2618512056774d5 TL;DR
flow: {
tables: [
{
blocks: [
{ id: 'audiobooks', name: 'block1' },
{ id: 'all', name: 'block2' }
{ id: 'family', name: 'block3' }
]
},
{
blocks: [
{ id: 'audiobooks', name: 'block1' },
{ id: 'all', name: 'block2' }
{ id: 'combo', name: 'block6' }
]
},
]
}
How to reproduce the issue:
Use the same id in different nested array of objects,
Version
- apollo-client@2.0.4
Sorry in advance if this post is very long, but I didn’t filter the response to help you guys see what’s happening
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 24
- Comments: 41 (7 by maintainers)
Actually I was able to fix by setting fetchPolicy to
no-cache
. It’s confusing what the difference is between this andnetwork-only
which I was using before. I think it’s a terrible decision to have the default be neither of these. I was very confused withoutnetwork-only
set before I’d make graphql calls and they would just not return. Turns out they were cached…which I’d expect to still return data from the call! Worst part is the id field that is causing wrong data for me is not even defined as an ID type in my schema!!! It’s just a String that happens to be calledid
.I have encountered the same bug, my current workaround/hack is to set a random ID for the affected types (effectivly turning off caching). Since
dataIdFromObject
only receives the object itself and not the whole “context” (like how it is nested) I dont see any option to do a better workaround.@hwillson (and the other maintainers) Also, I have extracted a minimal reproduction:
@eins78 Thanks for the reproduction. This isn’t a bug. Add
__typename
to theposts
selection set in your query, and it will work:When you don’t provide a
__typename
, Apollo’s in-memory cache uses a fallback method of associating data in the cache when it normalizes everything (you can read more about this here). This fallback isn’t foolproof and in your case when the data is normalized then attempted to be retrieved, the first set ofposts
will always be returned. But when you provide a__typename
the cache is able to use that data to properly differentiate between the differentposts
, so when retrieving everything works properly.Thanks for reporting this. There hasn’t been any activity here in quite some time, so we’ll close this issue for now. If this is still a problem (using a modern version of Apollo Client), please let us know. Thanks!
Also lost hours because of this issue 😦 This should not be closed!
I also recommend to check the following article about this issue https://kamranicus.com/posts/2018-03-06-graphql-apollo-object-caching
The solution with
__typename
doesn’t work for me. But this helped me:It is also documented here: https://www.apollographql.com/docs/react/advanced/caching/#normalization
The bug is still present in current version of Apollo Client. It still leads to data corruption when used as documented.
I updated all packages to latest version in the reproduction: https://codesandbox.io/s/0y9w819z0n
Hi all - this issue is still closed as there isn’t a bug here. This is the way the Apollo Client cache works - by default it treats entities with the same
__typename:id
as being the same objects, when it splits things out for normalization. Looking at the graphql response from the repro:Even though the
categories
are returned under 2 different years, they are still using the sameid
’s ofc1
andc2
. When Apollo Client splits this response up to store in its cache, it splits out all of the entities by__typename
andid
. So when things are stored in the cache, they look like this:The
c1
andc2
categories are only stored once, since they are seen as being the same entities due to their__typename:id
.That being said, if you don’t want this to happen and you’re using Apollo Client 3, you can disable normalization for
Category
types. This will make sure each category is seen as being independent, and is stored under each year. As a quick example, if you change the repro to include the following type policy:and re-run the repro and check the cache, you’ll now see:
Categories are no longer normalized, which means the duplicate categories exist under their associated years. You’ll see that the posts are still normalized, with
p1
top8
being split out as their own entities.Hopefully this helps clear things up. Thanks!
Thanks @charles-mathieus-jomedia ! Absolutely same issue just got me really hard. When I query my graphQL server results are perfect. But it seems that Apollo just takes prev values from cache and inserts them for every similar id. Someone explain the issue please.
I ran into this bug as well. When an item nested under one entity changed, the same item (same id) nested under a different entity would change as well when it was not supposed to.
Our workaround was to overwrite the original id with a unique ID on the incoming data (combined the entity id and original id in this case), then re-instate the original ID when passing it back to the database to be updated. Hacky, but works.
@hwillson No, adding
__typename
does not fix it: https://0y9w819z0n.codesandbox.io/The problem (seemingly) is the way the data is nested: the Posts are nested inside a Category, those are nested inside Year. The cache then considers all Categories of the same ID “equal” and thus returns the same list of Posts. But, because Category is nested in a Year, they are not actually the same. Yes, this is a weird data structure, but its allowed by the spec and it resulted from a real-world use case. As stated above, the only workaround we’ve found is to build a special ID just for the apollo cache, so a Category would have a “cacheKey” of
${YearID}--${category}
.I just ran into this issue.
{ ..., id: 'some-id', isPrimary: true }
.{ ..., id: 'some-id', isPrimary: null }
.Following the tip from @simplychaos to change
fetchPolicy
fromnetwork-only
tono-cache
solves my problem.For reference, I am using
apollo-angular
andInMemoryCache
.@nealoke Make sure you have the
possibleTypes
config set up correctly: https://www.apollographql.com/docs/react/data/fragments/#using-fragments-with-unions-and-interfacesWhen query field id rename can fix it. try it. @charles-mathieus-jomedia
like it
uid:id
Same problem for me. There should be a way to tell apollo client that the query response must be exactly as the network request data response. This is very frustrating.
I’m also facing this same problem.
Hello All , is there any solution for this issue? i am using apollo 2.6 and still see the same issue mentioned above.
Because this is a very confusing thing to explain, I forked the reproduction and added the workaround from our app: server: https://codesandbox.io/s/apollonestedcachingbug-u46hq client: https://codesandbox.io/s/basic-apollo-app-etgv0
It does not seem like this bug is actively worked on, but in any case I migrated the endpoint from my example above from (deprecated) apollo launchpad to codesandbox. I upgraded all dependencies and confirmed it is still broken.