apollo-client: Query Functionality with `onCompleted` is broken in v3.0.0 release (CodeSandbox repro)
Some core lazy querying functionality through useLazyQuery seems a bit off.
Specifically, when a lazy query (through a useLazyQuery hook) returns an error, then Apollo seems to start endlessly querying the server. The same thing happens if you give it a fetchPolicy of network-only (or anything that doesn’t search the cache first).
Related: https://github.com/apollographql/react-apollo/issues/4044
At the same time, if the lazy query function (returned by useLazyQuery) gets called more than 1 times, then no callbacks are fired. The onCompleted doesn’t fire again. The onCompleted fires on the 1st successful run of the “query” function and then consecutive invocations of the lazy query function, don’t trigger onCompleted callback (they should, since you can’t have conditional business logic based on whether the data is cached or not!)
Related: https://github.com/apollographql/react-apollo/issues/4000
Funnily enough, using client.query() works fine. All this used to work perfectly during the beta (I think I’ve verified that something occurred after @apollo/client@v3.0.0-beta.43), but now it doesn’t.
UPDATE: I’ve added a codesandbox that reproduces it
Intended outcome:
- Lazy query errors shouldn’t trigger endless API querying
- A
network-onlyfetch policy shouldn’t trigger endless API querying on a lazy query onCompletedshould fire every time a lazy query gets successfully executed
Actual outcome:
- Lazy query errors &
network-onlyfetch policy start an endless loop of requests onCompetedgets fired at most once regardless of the number of invocations
How to reproduce the issue:
- Take a lazy query and change the
fetchPolicytonetwork-onlyor force an API error on a lazy query - Click a button that triggers a lazy query multiple time, while observing the number of invocations of the
onCompletedcallback.
Versions System: OS: macOS 10.15.2 Binaries: Node: 12.18.0 - /usr/local/bin/node Yarn: 1.19.0 - /usr/local/bin/yarn npm: 6.14.4 - /usr/local/bin/npm Browsers: Chrome: 83.0.4103.116 Firefox: 72.0.2 Safari: 13.0.4 npmPackages: @apollo/client: ^3.0.2 => 3.0.2 apollo-link-error: ^1.1.12 => 1.1.13
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 37
- Comments: 52 (8 by maintainers)
@benjamn and @hwillson Thanks for tackling this.
Current State of things
As of the moment of writing, in
3.1.1:cache-firstquery withonCompletedand/oronErrorno longer re-renders endlessly 🎉network-onlyquery no longer pings the server endlessly 🎉Pending bugs
onCompletedcallback should always fire whenever a query is resolved (either from network or cache). https://github.com/apollographql/react-apollo/issues/4000Reproduction of pending bugs
You can observe both these bugs in the following codesandbox --> https://codesandbox.io/s/apollo-reference-equality-op12z?file=/src/App.js
To reproduce the
onCompletederror: ChangefetchPolicytocache-first, click “Run Query” multiple times and see howonCompletedonly fires onceTo reproduce the
variableswithuseLazyQueryerror: Click “Run Query” once and then start clicking “Change foo”. Clicking “change foo” should not cause a query to runAdditional Context
Out of the two bugs listed above (in the order that they are mentioned):
Thanks again!
This issue was fixed in https://github.com/apollographql/apollo-client/pull/6588, and will be coming in
@apollo/client@3.1.0very soon.@brainkim it’s not. Unfortunately, I believe it’s now worse than before, since
onCompletedgets only triggered once for all lazy queries withnetwork-onlypolicy, regardless of the number of times they are called. This means that even if I perform multiple network requests, I’ll still have only 1onCompletedcallback fired.Please refer to this comment https://github.com/apollographql/apollo-client/issues/6636#issuecomment-666310747 and its reproduction instructions to validate the bugs. I was able to validate them in apollo-client@3.5.3.
Should we re-open this?
@3nvi I believe both of the problems demonstrated in your reproduction are related to the fact that
useLazyQueryusesclient.watchQuerybehind the scenes, when it should just be usingclient.query:network-onlyquery when a variable changes is expected if the query is being watched, but would not happen if the query only executes when explicitly requested.onCompletednot firing is more loosely related, but I’m sure that’s something we could fix in the process of rewritinguseLazyQueryto avoid watching, since we should be able to hook into thePromisereturned byclient.query.Although we’re about to release v3.2.0 with the changes that are currently on the
release-3.2branch, we haven’t forgotten about this issue. We hope to include a fix in a 3.2.x (or a 3.3 beta) version soon.I’ve noticed that this is also happening with a regular
useQueryhook when anonCompletedfunction is specified (even if its a noop) and thefetchPolicyis set to anything exceptcache-firstorcache-onlyWould be nice to have a proper onComplete fired on refetch even if it’s from cache.
The most similar behavior I could come up with meanwhile was:
I just discovered that after upgrading from apollo 2 to 3.1.5 that my
useLazyQueryare not always firing the onCompleted. Current workaround for me seems to be changing usage of useLazyQuery to:This issue was not fixed for three years…
I’m having the same problems with
useLazyQueryHeads up: we’re not quite ready to publish
@apollo/client@3.1.0yet, but I’ve published an@apollo/client@3.1.0-pre.0release that includes #6588, if you want to try that in the meantime. 🙏Update: thanks to @3nvi’s reproduction, I can confirm the fix: https://codesandbox.io/s/apollo-reference-equality-t0ttx
👍 on this, thanks for the work you’re putting into this project!
I also have an issue with
useLazyQuerythat I think might relate to this?I have an
ApolloClientinstance that I use in myApolloProviderthat I need to reinitialize once in a while because a couple of settings change during the lifetime of the app (mostly HTTP headers and connection params). Therefore, instead of having the client be created outside the scope of my React tree, it’s generated within a custom hook. However, it seems like every time there’s a new value passed toApolloProviderfor theclientprop, all queries usinguseLazyQueryare relaunched automatically – and they seem to be launched with the latest variables they were called with. I would expect that they wouldn’t be launched until there’s another call to the functions provided by theuseLazyQueryhooks, right?Maybe there’s something wrong with the way I’m reloading the client though, and that it shouldn’t go through React updates. I couldn’t find any documentation on it. Let me know!
I’m on 3.1.1 and onCompleted never calls if a useLazyQuery has its result cached.
I don’t think I’ve seen this mentioned yet as it probably comes from the same underlying behavior…but a
useLazyQuerywith aonCompleteddoes not get called again if a user specifies arefetchQueriesarray in auseMutationmethod call.Such as
The bug calling onCompleted looks like a long-running holdover from 2.x. https://github.com/apollographql/react-apollo/issues/2177
Thank you so much @benjamn ! It’s working for me, great!