apollo-client: 2.0 not clearing error after refetch
Intended outcome: data.error should be cleared after successful refetch.
Actual outcome: after error a successful refetch does not clear the error. (In fact I dont think query data is set to undefined on error either, it also retains previous response if there was one. Not sure if that caching and is possibly expected on network-only calls?)
How to reproduce the issue:
1. turn graphql server offline
2. as expected queries return an error { myData: undefined, loading: false, error: 'Error: Network error: Failed to fetch' }
3. turn graphql server back online and do a refetch
4. query returns data successfully but error is not cleared { myData: { uuid: abc123 }, loading: false, error: 'Error: Network error: Failed to fetch' }
Version
- apollo-client@2.0.0
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 32
- Comments: 32 (4 by maintainers)
Commits related to this issue
- Fix: clean up properly after a graphql error replace react-apollo with npmjs.com/package/react-apollo-temp which is a fork that provides a workaround to this issue https://github.com/apollographql/ap... — committed to newsuk/times-components by BernieSumption 6 years ago
- fix: clean up properly after a graphql error (#501) replace react-apollo with npmjs.com/package/react-apollo-temp which is a fork that provides a workaround to this issue https://github.com/apollog... — committed to newsuk/times-components by BernieSumption 6 years ago
This issue prevents letting users retry failed queries manually. I would assume this is a really common use case. Any ETA on a fix?
I am running into this issue as well… strangely enough it seems like the unit test for this scenario was removed some months ago.
The issue is fundamentally caused by ES6 Observables terminating the stream when an error is sent to an observer. In this case, any kind of error in the query causes the react-apollo component to get dropped (from here to here to here), and the subsequent teardown of the query is just a further consequence. The components themselves don’t contain much subscription logic beyond the mount/unmount lifecycle and thus remain unaware the queries were torn down.
It seems like the subscription logic for react components might need further consideration, or perhaps a different way to handle error conditions.
In either case, here is my own short-term workaround which should serve as a drop-in replacement for the normal
graphqlfunction:Ok, I’ve spent many many hours debugging this now with no luck whatsoever. I’ve checked both
apollo-clientandreact-apolloto see if I could fix the error, but no matter what I try, I cannot make this problem go away.I could really use some help from someone who understands this codebase better. This is a serious issue, and will affect any user who may have a spotty internet connection.
To summarize the problem and how to reproduce it: after receiving a network error, components wrapped with the
graphqlhigher order component are not receiving updates when refetch is run, even though the queries are executed.The way you can reproduce this is to set up one component with a query, wrapped in the
graphqlhigher-order component. You will need a local apollo server to serve the requests. Load up your app, then after it’s loaded, turn off the server, and cause the query to be refetched. You should get a network error.Then turn the server back on and refetch again. In your server logs you should see that the query is being run. However, the component will not be updated with data from the server (i.e. render is not called - the component does not receive new props).
From what I can gather, after the refetch completes,
QueryManager.broadcastQueries()is called. When it tries to broadcast the query that was refetched, it’s essentially a no-op sincethis.queries[queryIdOfQueryThatFailed].listenersis an empty array.I tried to address this by commenting out
ObservableQuery.prototype.tearDownQuery, which gets called when the query errors out. I also commented out this line.Indeed, that prevents the listeners from being removed, but when the listener is called (
QueryManager.prototype.queryListenerForObserver)observer.nextdoesn’t do anything because the observer is marked as closed (this line).@msmfsd In my case it was pretty easy because my components are already using a wrapped version of
graphql()which adds a few extra things (specifically, some build-step oddities). I keep it in a utilities script that is imported instead of the regular HOC, so my components automatically get any improvements I make.I’m sending a PR which incorporates the approach I took plus a unit test that demonstrates the issue. Would love to get some feedback and/or get it merged asap (…or if I did it entirely wrong because this is my first github PR…).
@dotansimha I forget where I found this, but I read on another github thread somebody suggesting the following workaround: Overwrite the
GraphQL.prototype.dataForChildmethod so it includes the property,retry.You should be able to find the section in react-apollo.browser.umd.js (in the react-apollo package) that contains these lines:
You can change that to be this:
Then if your query results in a network error, you can at least call
this.props.data.retry()and it preserves the ability to refetch and all that.Instead of overwriting node_modules, the way I set this up was to drop a file into a folder in my project called
haxand add it there. Here’s a link to a gist of that file.Now, you just import graphql from
App/hax/graphqlinstead of react-apollo. It’s a shitty workaround, but then again, there aren’t many good options here.The other thing you can do is use the
RetryLinkand make it so that it never stops retrying.Thanks @adambom ! I used your workaround and it works! (If someone else needs it, I published is as
react-apollo-temp@2.0.2to NPM).@jbaxleyiii can the above be used as fix for this issue?
@jbaxleyiii error template is here: https://github.com/msmfsd/apollo-error-tmpt-pr-2513
NOTE: it was tricky to trigger an realistic error off and on without an external server…