apollographql / apollo-client

:rocket:  A fully-featured, production ready caching GraphQL client for every UI framework and GraphQL server.
https://apollographql.com/client
MIT License
19.33k stars 2.65k forks source link

`@client` field from wrong query call when query is duplicated #9353

Open gabsprates opened 2 years ago

gabsprates commented 2 years ago

Intended outcome:

I reproduced the bug (well, I believe it is a bug) using the SWAPI GraphQL API and you can check it here: https://codesandbox.io/s/local-only-wrong-query-call-cvnj3

My original intention was creating a function to help me identify places where I'm using local-only fields (@client) without its dependencies, as I'm calculating the local field based on a value that comes from a query request. Then, if I try to read a field (the dependency) and it is undefined, I deduced it was not asked on the query because, by GraphQL, I can't have a undefined form non-nullable fields.

The problem starts when I needed to do two queries in different places and only one of them were asking for the @client field. They were calling the same query in the schema, with same variables, but requesting different data:

  1. first query:
    query { person(personID: 1) { id name } }
  2. second query:
    query {
    person(personID: 1) {
    id
    birthYear
    birthYearFormatted @client
    }
    }

I was expecting it to resolve my @client field only after the second query gets its response from API, then I would have the birthYear dependency.

Actual outcome:

The problem I faced was that right after the first query response arrived, it tried to solve my @client field, leading to my undefined handler, throwing errors to my application and my second query didn't run.

After talking with my team mates, and as this person() {} query accepts a different variable called id, we tried to request the second by id instead of personID and the whole stuff worked fine: the two queries run and the local resolver did its job. Without my undefined handler, I need to provide an fallback value and it will be updated after the second query runs and update the cache for the Person:id reference.

I started to believe we may have a problem with the way Apollo's InMemoryCache is looking for the the data to resolve the typePolicies; or maybe it is merging stuff it shouldn't, or in a wrong moment.

How to reproduce the issue: You can use the example I did in CodeSandbox, which is already with the error. To see it working, you can run the query passing id instead of personID (uncomment lines 11 and 12 and delete lines 16 and 17

Versions In the example I used:

benjamn commented 2 years ago

Thanks for the reproduction @gabsprates!