"Loading" stays true when the same result is returned twice in Apollo Client 3.6.9
See original GitHub issueThis has been a long-standing issue that I’ve seen numerous people bring up, but I may have found the cause.
Here is the problem:
const request = {
query: gql`
query test($foo: String) {
test(foo: $foo) {
value
}
}
`,
variables: { foo: "bar" },
notifyOnNetworkStatusChange: true
};
const observer = client.watchQuery(request);
observer.subscribe({
next: ({ loading }) => {
console.log(loading);
}
});
When the GraphQL query returns the same result successfully and subsequently, even if the variables have changed, the loading
flag remains true
even after the second request returns successfully. It does not return back to false
until the result returns something different than it did the last time.
The expected outcome is that loading
flips to true
when the request is in flight and then flips back to false
after the request completes, even if the result is the same between the two requests.
I believe there’s a good chance this bug is due to this bit of code:
private reportResult(
result: ApolloQueryResult<TData>,
variables: TVariables | undefined,
) {
const lastError = this.getLastError();
if (lastError || this.isDifferentFromLastResult(result)) {
if (lastError || !result.partial || this.options.returnPartialData) {
this.updateLastResult(result, variables);
}
iterateObserversSafely(this.observers, 'next', result);
}
}
I believe that maybe it was supposed to be:
private reportResult(
result: ApolloQueryResult<TData>,
variables: TVariables | undefined,
) {
const lastError = this.getLastError();
if (lastError || !result.partial || this.options.returnPartialData || this.isDifferentFromLastResult(result)) {
this.updateLastResult(result, variables);
iterateObserversSafely(this.observers, 'next', result);
}
}
In the former, the observer will never iterate if the request is successful and the next result is the same as the previous result.
Maybe this was just a minor coding oversight. But it would be nice to get feedback from the Apollo Client team to make sure this aligns with their thinking.
The way I was able to confirm this was the issue is that, when I added a timestamp of the request to the GraphQL API result, the problem was completely gone. So when the result is different with each request, it works as intended. But I shouldn’t have to do this in a production setting.
Note I am running @apollo/client
3.6.9 and graphql
16.6.0, both the newest versions. I am also not using React. So if a fix for this was previously introduced for React, I’m afraid it wouldn’t have fixed the root of the problem in Apollo Client itself.
Many tickets about this have been opened by others, all with suggestions of different workarounds, like changing networkPolicy
to network-only
, no-cache
, or cache-and-network
. Or even setting pollInterval
to 0
. But none of these worked for me, presumably because the root problem seems to be related to the conditions under which the observer will iterate. But it is interesting that the cache is still checked even when using a networkPolicy
of no-cache
.
Here are some of the related issues I found on this topic:
https://github.com/apollographql/apollo-client/issues/6334 https://github.com/apollographql/apollo-client/issues/9845 https://github.com/apollographql/apollo-client/pull/9844 (another attempted fix, but I wonder if this one was overkill) https://github.com/apollographql/apollo-client/pull/6417 (a merged PR from two years ago attempting to fix this, but not successfully) https://github.com/apollographql/apollo-client/issues/9689 (maybe related) https://github.com/apollographql/apollo-client/issues/9668 (also maybe related)
Would greatly appreciate any insight on this. I currently don’t have any other workarounds other than to add a timestamp to our API, but since we have a public-facing API, this would not be ideal.
Thank you!
Issue Analytics
- State:
- Created a year ago
- Comments:9 (5 by maintainers)
Top GitHub Comments
The fix was just merged and will go out in an upcoming patch release (3.7.1). Thanks all!
Hey @hwillson,
This one gave me a run for my money to cut down to a reproduction, but I finally got it:
https://codesandbox.io/s/competent-worker-7qu3p1?file=/src/index.jsx
Turns out there are some more specific criteria that trigger this bug. In working on the reproduction, I found this error only happens under these conditions:
Of note, the array of objects is being passed as a JSON GraphQL type via the scalars provided by this package: https://www.npmjs.com/package/graphql-scalars
…but that GraphQLJSON definition is set on the server, not the client…
I have not yet tested whether or not this issue still happens with a natively provided data type instead of a custom scalar, but seeing as though Apollo Client should be naive to that type (I think), that may not have any bearing on the problem, at least in my mind.
But I wanted to get your feedback and see whether that’s consistent with your thinking or not.
As for my proposed solution, I’m less certain now in light of what I found after creating this reproduction. But that’s beyond my knowledge.
Thanks!