apollo-client: UseLazyQuery does not trigger onCompleted if result remains the same
Intended outcome:
I want to query manually using useLazyQuery
hook and get the result in the onCompleted
callback function. I also use a no-cache
fetch policy.
Actual outcome:
The onCompleted
callback function is only triggered the first time, if the result of the query has changed.
After the first call, I can see in the Network
panel of my browser that the query is being executed everytime I click on the button but no further event is being fired.
It would be logical that the onCompleted
callback function triggers no matter what the fetch policy is.
How to reproduce the issue:
function TestComponent() {
const [execQuery] = useLazyQuery(MY_QUERY, {
fetchPolicy: 'no-cache',
onCompleted: result => {
console.log('execQuery has completed'); // only fires the first time
},
});
return (
<>
<button onClick={() => execQuery()}>click me</button>
</>
);
}
Versions
apollo-client : 3.5.7 react : 17.0.2
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 38
- Comments: 24 (1 by maintainers)
Commits related to this issue
- fix: prevent timer stalling Apollo has an [issue?] where it won't always call the callbacks `onCompleted`/`onError` when retrieving cached queries. Preventing the query from caching (thereby forcing ... — committed to mojotech/helios2 by RVRX 2 years ago
- fix: prevent timer stalling Apollo has an [issue?] where it won't always call the callbacks `onCompleted`/`onError` when retrieving cached queries. Preventing the query from caching (thereby forcing ... — committed to mojotech/helios2 by RVRX 2 years ago
fetchPolicy: 'cache-and-network'
works for me.Apollo client library which has over 2m downloads per week doesn’t have any docs regarding how onCompleted behaves. It works totally randomly depending on fetch-policy and apollo/client version. This subject is not new…waiting for over 2 years and still no solution/no docs.
We changed a number of things about how
useQuery
anduseLazyQuery
are implemented internally in Apollo Client v3.6, so I would recommend attempting to update withnpm i @apollo/client@latest
when you have a chance!For example,
useLazyQuery
is now implemented (more fully) in terms ofuseQuery
, so it should now (with any luck) inherit the sameonCompleted
andonError
calling behavior asuseQuery
. Even if that behavior is undesirable, this means we can adjust/fix both hooks simultaneously, going forward.@jmtimko5 I don’t think this is a bug, it is just the default behavior. It can be a bit annoying that the default behaviour isn’t
network-only
, but it is not a bug 🤷Another workaround may be to not rely on
onCompleted
and use the promise’sthen()
instead:(Also, not sure when lazyQuery started returning a promise. It doesn’t appear to be in v3.3, but is in v3.7.)
This is pretty brutal bug honestly. It’s completely unexpected behavior that has led to several bugs leaking into production in our product. Can someone on the Apollo side investigate and confirm it is not present on the latest version. I do see a pattern on a lot of these Apollo bugs where there is no attention for months, a new version gets released, then maintainers say please upgrade to the latest version. There is no investigation whether the bug is still present in the new version. Often people confirm the latest version still has the bug, and then the bug remains open or worse it is preemptively closed.
Hi, you need to use
notifyOnNetworkStatusChange: true
. Can confirm thatnotifyOnNetworkStatusChange
solves the problem.This is what I ended up doing to resolve the issue. When in doubt, rely on the underlying JS API, if there’s not some huge tradeoff in readability. I don’t know how
onCompleted
works. I DO know how Promises work.Ran into this again in a customer demo, just a bummer. 1 year to the day where this caused a production fire previously.
The
onComplete
callback didn’t always fire when triggering calls quickly after one another, even though all the calls were executed in the network tab. The promise approach also works for me.@benjamn It becomes a question of whether it’s a good design choice to have
onComplete
only fire the first time. Keen on thoughts. Thanks for the explainer on the recent changes.