Two queries loop forever when requesting different parts of same object
See original GitHub issueIntended outcome: I have a CRUD-like application where the user may create, read update or delete objects of different types. Let’s say we are talking about “countries” and “cities”. I can then execute queries like this:
countries { id name }
or this:
cities { id name }
However, different users have different permissions to work with these objects, and the server owns the logic about this. To indicate to the React app whether Create, Edit or Delete buttons should be visible for the current user and a particular object type, there is a “permissions” object available in the GraphQL schema.
Then we can make queries like this
permissions { countries cities }
…and get back lists of enum values (CREATE, READ, UPDATE, DELETE). An example response for the query above is:
permissions { countries: ['READ'], cities: ['CREATE', 'READ', 'UPDATE'] }
If a specific React component is handling Countries, it may then make the following query:
countries { id name } permissions { countries }
…and another component handling Cities may execute this query:
cities { id name } permissions { cities }
Actual outcome:
This worked fine until 3.0.0-beta.46. But now, at least when two queries like those mentioned above are executed simultaneously, there is in an infinite loop of queries against the graphql server.
The problem seems to be around the permissions
object. My conslusion is that the cache is having trouble when different parts of the object are coming in via different queries, for an object that has no identity.
The issue goes away if I do any of the following:
- Remove one of the queries
- Remove the
permissions
part of at least one of the queries - Expand the permissions part so all queries request the complete permissions object
- downgrade to a version less than 3.0.0-beta.46
How to reproduce the issue: I’ve uploaded a repro project here: https://github.com/nordvall/apollo-query-loop
In the real app I can see the queries running off in the Networing tab in Chrome. In the repro project I’ve included some console logging, so you can see the looping in the Console tab instead.
The real server is running GraphQL.NET, so I’ve tried to replicate the schema in the Apollo resolver object model.
Versions @apollo/client: 3.0.0-beta.53 graphql: 14.6.0 react ^16.12.0
Issue Analytics
- State:
- Created 3 years ago
- Reactions:5
- Comments:14 (4 by maintainers)
@nordvall Can you tell me more about this
Permissions
type?I can see that the desired behavior is for the fields of this
Permissions
object to be merged over time, so you don’t lose data fetched by different queries. Is that because thePermissions
object is conceptually a global singleton object, so it’s always safe to merge new fields into it? Or should the merging ofPermissions
object fields apply only to objects requested via the rootquery { permissions }
field?To achieve the first behavior (global singleton), you can give
Permissions
objects a constant identity withkeyFields: []
:To achieve the second behavior (merge only
query { permissions }
objects when they collide):Either one of these approaches will stop the mutual clobbering of data that’s triggering the refetching. Obviously it would be ideal to detect and warn about situations like this, but I want to be sure the possible solutions that we would recommend in those warning messages actually meet your needs.
Judging by the provided reproduction (thanks!),
@apollo/client@3.0.0-rc.5
should fix the endless network request loop, thanks to #6448.