Query silently fails with multiple paginated queries with differing child fields
See original GitHub issueHow to reproduce the issue: Visit https://codesandbox.io/s/admiring-dhawan-tjtz5?file=/src/client.js
Wait for query A to finish. This is a ‘heavy’ query, with a small limit, and a load more button. We are using the offsetLimitPagination
typePolicy here to enable ‘load more’ to work.
Now click on B at the top. This queries the same field as A, but with a much larger limit, and only one field. You might imagine we went from some sort of infinite scroll detailed list view to a very high level but broad overview.
Now click on A at the top to go back to query A.
Query A silently fails. There is no data, and no error, and no console explanation that there is a problem somewhere.
It’s very natural for separate parts of an app to use the same field with different limits and subfields. I am trying to upgrade from Apollo 2 where I was previously using updateQuery with fetchMore for this behavior.
Versions 3.4.7
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:7 (4 by maintainers)
Hi @benjamn I noticed you released 3.4.8 which includes https://github.com/apollographql/apollo-client/pull/8642
I’ve created a new codesandbox with 3.4.8 here: https://codesandbox.io/s/inspiring-rgb-y1m2z?file=/src/App.js
The original bug I reported appears to be fixed. However I note a new bug:
A - 5
toA - 10
A - 5
now (not 100% ideal, but much better than displaying nothing as before). However if you now click ‘load more’, the network request fires, but the component does not update. It stays stuck onA - 5
, i.e. fetchMore is no longer functioning.Thanks for the rapid response. I appreciate all the effort that has gone into Apollo, it’s a critical part of our software, and we’re very grateful for it.
The
setLogVerbosity
command is helpful, thank you.However I’m still surprised by this behavior. Adding a valid query to a completely unrelated part of an app can cause a query elsewhere to fail silently (i.e. break), and only if the user takes a specific path (e.g. hits query B before query A). This is a heavy maintenance burden, any time you add a query you now need to be worried that you accidentally broke another, unrelated, part of your app, and possibly one that you’ve never even personally worked on. Presumably you need to check the field resolvers for every field in the query you just added (and it’s not unusual for us to have 50-100 fields), and if there are pagination style rules for them, then you need to look for any other query that shares those fields. And if they are shared, you now need to start modifying an unrelated component that was working correctly before, in a way that’s only testable by navigating through the app in a very specific order.
Unfortunately both of your proposed solutions have a bit of a ‘band aid’ feel to them rather than addressing the underlying issue. My screen for query A is built with query A in mind; it expects the fields in the query to be there, and expects e.g. rocket to never be null (and indeed in the hypothetical gql schema rocket will be non null, and the auto-generated typescript typings will also state it’s never null or absent). To now tell the developer of component A that ‘the rocket field might not be there, or if it is, it might be null’ even though it’s in the query, and the server guarantees it is not null, seems off. And in my real world scenario, we have close to a hundred fields under the equivalent of the
Launch
object in this specific query that I’m encountering this issue for.You mention some other solutions, I’d be very keen to hear them. Specifically, it seems like if query A can’t resolve via the cache, then it should resolve via the network. Or ideally, perhaps we can segregate the data in the read policy based on whether it has all the required fields. In no situation would I expect it to not return anything, i.e. neither data nor an error.
Is
partialRefetch
a solution here? It appears to have been deprecated, but it does seem to fix the behavior. However it causes query A to fire twice when you navigate back to it in the code sandbox.