-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useQuery
onCompleted
callback is one render out of date
#12316
Comments
This seems to only happen for cache hits. What happens here is that we get the cache hit & start a rerender before the ref for the callback can be updated in a I'm trying this with a It comes down to: we need to deprecate and remove these callbacks at some point. |
It seems my attempted fix in #12319 works in your replication. Could you please try it in your app and report back? npm i https://pkg.pr.new/@apollo/client@12319 |
I updated my I see the same bug. |
That is weird - I did the same and it disappeared for me. That said, I believe that is all we can do from our side to try and fix this - I'll check in with my colleagues tomorrow, but I don't see a good way forward here - we are bound by React's limitations for this one and breaking those would mean bugs in other cases. React unfortunately invites those "stale reference" situations. I would ultimately recommend you to migrate off the Here's also a blog article why React Query removed these callbacks - we share a lot of their concerns by now. |
This is ultimately what we've already done, but the workaround I found also required moving off of Our actual pattern was: useQuery(..., {
onCompleted: (data) => {
setExternalStore(transformData(data));
}
); This ensured we only updated our store when it was required, and not every time the hook ran. (Yes, we're dealing with cache hits, but if the What I wouldn't want is const { data } = useQuery(...)
setExternalStore(transformData(data)); because that will cause extra re-renders every time the hook runs, since the transformation creates a new object. |
Why not const { data } = useQuery(...)
useEffect(() => {
setExternalStore(transformData(data));
}, [data]) synchronizing with external systems is pretty much exactly what |
Issue Description
I am querying a GraphQL endpoint with dynamic variables. I expect to transform the data inside the
onCompleted
function, and set a variable based on the dynamic variable. However, the Apollo client is caching the oldonCompleted
callback, so that it's one out of date, which gives me incorrect data.To show this, I've written an MRE which console logs inside the
onCompleted
function. From the parent, I pass a prop down which is printed in the log statement. The prop is a number and each re-render increases it by one. Instead of seeingn
in my logs, though, I seen - 1
for everything after the first one.MRE code
index.tsx
App.tsx
package.json
If it'll load, I've also made a Repl here: https://replit.com/@DavidAntonucci/ApolloBugMRE#src/App.tsx
Link to Reproduction
https://replit.com/@DavidAntonucci/ApolloBugMRE#src/App.tsx
Reproduction Steps
No response
@apollo/client
version3.12.8
The text was updated successfully, but these errors were encountered: