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-only
fetch policy shouldn’t trigger endless API querying on a lazy query onCompleted
should fire every time a lazy query gets successfully executed
Actual outcome:
- Lazy query errors &
network-only
fetch policy start an endless loop of requests onCompeted
gets fired at most once regardless of the number of invocations
How to reproduce the issue:
- Take a lazy query and change the
fetchPolicy
tonetwork-only
or 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
onCompleted
callback.
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-first
query withonCompleted
and/oronError
no longer re-renders endlessly 🎉network-only
query no longer pings the server endlessly 🎉Pending bugs
onCompleted
callback 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
onCompleted
error: ChangefetchPolicy
tocache-first
, click “Run Query” multiple times and see howonCompleted
only fires onceTo reproduce the
variables
withuseLazyQuery
error: 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.0
very soon.@brainkim it’s not. Unfortunately, I believe it’s now worse than before, since
onCompleted
gets only triggered once for all lazy queries withnetwork-only
policy, regardless of the number of times they are called. This means that even if I perform multiple network requests, I’ll still have only 1onCompleted
callback 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
useLazyQuery
usesclient.watchQuery
behind the scenes, when it should just be usingclient.query
:network-only
query when a variable changes is expected if the query is being watched, but would not happen if the query only executes when explicitly requested.onCompleted
not firing is more loosely related, but I’m sure that’s something we could fix in the process of rewritinguseLazyQuery
to avoid watching, since we should be able to hook into thePromise
returned byclient.query
.Although we’re about to release v3.2.0 with the changes that are currently on the
release-3.2
branch, 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
useQuery
hook when anonCompleted
function is specified (even if its a noop) and thefetchPolicy
is set to anything exceptcache-first
orcache-only
Would 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
useLazyQuery
are 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
useLazyQuery
Heads up: we’re not quite ready to publish
@apollo/client@3.1.0
yet, but I’ve published an@apollo/client@3.1.0-pre.0
release 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
useLazyQuery
that I think might relate to this?I have an
ApolloClient
instance that I use in myApolloProvider
that 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 toApolloProvider
for theclient
prop, all queries usinguseLazyQuery
are 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 theuseLazyQuery
hooks, 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
useLazyQuery
with aonCompleted
does not get called again if a user specifies arefetchQueries
array in auseMutation
method 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!