New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query returns `undefined` when same cache object is in multiple query responses #2678

Open
irace opened this Issue Dec 19, 2018 · 7 comments

Comments

Projects
None yet
2 participants
@irace
Copy link

irace commented Dec 19, 2018

I have two queries in components that are on screen at the same time – one (me) returns the current user, and another (group) returns all members of a group. Once cached, the cached results of each query look as follows:

ROOT_QUERY
  me: User
    User:bryan-irace
  group({"id": 1}): Group
    Group:some-group-name
      members: GroupMembers
        results: [User]
          0: User:bryan-irace
          1: User:kevin-grant

I am seeing some very strange behavior when the User model returned by the me query is also included in the members.results array returned by the group query. Specifically, the me query’s callback is invoked multiple times:

  1. data.me returned undefined (network request has not occurred and cache has not been populated yet)
  2. data.me returns the correct model (model is now stored in the cache)
  3. data.me returns undefined again, despite the model being present on disk

This third invocation is problematic – I don’t know why it is being triggered to begin with, but if it’s going to be triggered, data.me should certainly be populated.

I can fix this problem by either:

  1. Removing the groups query altogether
  2. Modifying the data such that the user returned by the me query is no longer a group member

Obviously neither of these are suitable workarounds, but in both cases, the third me query callback invocation does not occur.

Please advise 🙏

@irace

This comment has been minimized.

Copy link
Author

irace commented Dec 19, 2018

If it helps, here are the two different variations on the same model, the first from the me query and the second from the group query:

"admin": true,
"firstName": "Bryan",
"lastName": "Irace",
"bio": "Push code too late on a Friday – what is wrong with me",
"professions": [{
  "id": 2,
  "name": "Software Developer",
  "__typename": "Profession"
}, {
  "id": 8,
  "name": "Polyglot Engineer42",
  "__typename": "Profession"
}],
"phoneNumber": "+15559274956",
"city": "Chicago, NY",
"email": "bryan@foo.bar",
"website": "https://irace.me",
"linkedinUrl": null,
"facebookUrl": null,
"instagramUrl": null,
"twitterUrl": null,
"googleUrl": null,
"yelpUrl": null,
"foursquareUrl": null,
"slug": "bryan-irace",
"tags": [],
"avatar": {
  "large": "https://some/avatar/url",
  "thumbnail": "https://some/avatar/url",
  "__typename": "UserAvatar"
}
"firstName": "Bryan",
"lastName": "Irace",
"professions": [{
  "name": "Software Developer",
  "__typename": "Profession"
}, {
  "name": "Polyglot Engineer42",
  "__typename": "Profession"
}],
"slug": "bryan-irace",
"avatar": {
  "large": "https://some/avatar/url",
  "thumbnail": "https://some/avatar/url",
  "__typename": "UserAvatar"
},
"tags": [],
"__typename": "User"
}
@sbrichardson

This comment has been minimized.

Copy link

sbrichardson commented Dec 31, 2018

Is there an id field that you left off? Not having an id field will cause a lot of issues, since it's used by apollo when normalizing to the cache.

@irace

This comment has been minimized.

Copy link
Author

irace commented Dec 31, 2018

@sbrichardson Thanks for getting back to me. In this case, the slug field is the unique identifier used for caching purposes.

@irace

This comment has been minimized.

Copy link
Author

irace commented Jan 2, 2019

OK, I (mostly?) figured this out.

First, if caching was turned off, this bug did not manifest itself.

Ultimately, the issue is that I was making one query (modified for brevity) like:

user {
  slug
  profession {
    name
  }
}

And another query like:

user {
  slug
  profession {
    id
    name
  }
}

Even though the users were the same, and using slug as their cache ID, the fact that the nested professions were not being correctly identified as the same reference (due to one having an id property and the other not), the cache was in a weird state and incapable of realizing that the two users were – in fact – the same reference.

@irace

This comment has been minimized.

Copy link
Author

irace commented Jan 2, 2019

This is a pretty easy mistake to make though, and the fact that this just returns undefined when the query’s data is visible in the cache via the Apollo inspector makes it really hard to figure out what's going on. No errors or anything.

@sbrichardson

This comment has been minimized.

Copy link

sbrichardson commented Jan 4, 2019

Yes I've ran into that issue, was going to mention, typically it manifests if you remove an id field from a selection set accidentally, such as in a table UI, editing table columns to build a gql query dynamically.

Unfortnuately, this issue comes up and is resolved but the github issues are spread around in react-apollo, apollo-cache etc, so it compounds the troubleshooting effort.

https://www.apollographql.com/docs/react/advanced/caching.html#normalization

@irace

This comment has been minimized.

Copy link
Author

irace commented Jan 4, 2019

@sbrichardson That documentation that you linked to doesn’t really give any indication that a missing cache key on a child object would prevent the parent object from being properly normalized. It seems like this should theoretically be something that Apollo can handle, or at the very least provide a more helpful error message?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment