apollo-client
apollo-client copied to clipboard
Weird Merging of Duplicate Array
For a given query which responds something like this ->
{
foo
{
bar {
c [{a}]
}
}
bar
{
c[{b,c,a,d}]
}
}
Intended outcome:
the intended outcome is either a union of the two or replace one with other -> c = [{a}] or c = [{b,c,a,d}]
Actual outcome:
the response object will contain c as [{a,c,a,d}] -> merge of the two instances with values being replaced
How to reproduce the issue:
Versions
System: OS: macOS 13.0.1 Binaries: Node: 16.14.2 - ~/.nvm/versions/node/v16.14.2/bin/node Yarn: 1.22.19 - ~/.nvm/versions/node/v16.14.2/bin/yarn npm: 8.5.0 - ~/.nvm/versions/node/v16.14.2/bin/npm Browsers: Chrome: 107.0.5304.110 Safari: 16.1 npmPackages: @apollo/client: 3.6.2 => 3.6.2 apollo-server-core: ^3.9.0 => 3.11.1 apollo-server-express: 3.9.0 => 3.9.0
Hey @yj7! Thanks for opening the issue. Have you looked at our docs regarding cache field behavior? From what I understand, you may need to tweak the default merge strategy used to ensure the fields are properly written to the cache.
If you've got type/field policies defined that are setup as you expect and you believe this is a bug, would you be willing to get us a reproduction of the issue to better figure out what might be happening here? Thanks!
Hey @jerelmiller -> Here is the reproduction. https://github.com/yj7/apollo-bug-repo.
Trying to explain the issue again with the example repo as reference.
query AllPeople {
user{
id,
name,
fruits{
id,
name
}
}
people {
id
name
fruits{
id
name
}
}
}
This is the query being fired -> User object will always return details about Sara Smith -> with the fruits array containing 3 items
{ id: 1, name: 'apple', },
{ id: 2, name: 'mango', },
{ id: 3, name: 'banana', }
The people query will return an array of Persons including Sara Smith. In this query the fruits array will return only 1 fruit banana.
Since Sara Smith is returned twice as part of the same response with 2 different fruits array. Apollo Merges the two array and gives a mixed array.
Actual Output
{ id: 3, name: 'banana', },
{ id: 2, name: 'mango', },
{ id: 3, name: 'banana', }
Expected Output
{ id: 1, name: 'apple', },
{ id: 2, name: 'mango', },
{ id: 3, name: 'banana', }
Or
{ id: 3, name: 'banana', }
Also another observation -> the order of the query affects the result / output. If the query is changed to
people {
id
name
fruits{
id
name
}
}
user{
id,
name,
fruits{
id,
name
}
}
Result for Sara Smith -> Fruits is
{ id: 1, name: 'apple', },
{ id: 2, name: 'mango', },
{ id: 3, name: 'banana', }
Hi @yj7 👋🏻 can you help me understand these lines?
https://github.com/yj7/apollo-bug-repo/blob/148b69c5510e703447d0ba829636153c25849e72/src/schema.js#L32-L37
@bignimbus That is just a hack for this reproduction. The effect i am trying to achieve is -> based on the query the fruits object can have a list of all items or a subset of the items.
Imagine it as when querying people we only send the favourite fruit but when querying user we send all the fruits.
Thanks @yj7, we'll take a closer look at your reproduction as soon as we can. As @jerelmiller noted, type and field policies exist so the developer can control how to handle updates of list types. Did defining a policy help address the issue you saw in your application?
@bignimbus Defining a policy did not help ... was getting the incorrect merged array in the update cache function. What helped was changing the order of the query.
@bignimbus Any update on this?
I have encountered same issue Node.js v21.5.0 npm 10.2.4 OS: macOS 14.0 Firefox 121.0 (64-bit) @apollo/client 3.8.8
Server (rust) juniper 0.15.11
HTTP requests come with correct payload. This happens only when cache is involved
Code to reproduce:
- back end on rust https://gitlab.com/yar.ua/dictionary-service-be/-/tree/54439693beac9d2dd45f1a8cf433f7e7d7a29c23
- front end https://gitlab.com/yar.ua/dictionary-service-fe/-/tree/b38bd61e8753a233b9d9708c5a416ffcdd2e4728 Steps: On the page click on the first item in the left column (view should load), then click on the second item in the left column (another set of data should load), finally click again on the first item (now the content is mix of both items)
We faced a similar issue. I'll replace our model names with generic examples. In our case we had an array of Person which contained an array of Pet.
If PersonA had Dog in Pet and if PersonB also had Dog in Pet, then PersonB's Dog would become the same as PersonA's. Our Dog object would share the same id but had different attributes like name, but the name and other attributes from PersonA's Dog was being used in PersonB's Dog.
In our case, we renamed id to dogId and it worked as expected. So I think there is some weird behaviour with Apollo and id for the same model being used in different contexts.
I'm not exactly sure if this is the same issue as the original, but thought I would share it in case it helps anyone