apollographql / apollo-client

:rocket:  A fully-featured, production ready caching GraphQL client for every UI framework and GraphQL server.
https://apollographql.com/client
MIT License
19.4k stars 2.66k forks source link

useLazyQuery executes query twice the first time on 3.6.x #9655

Closed dairyisscary closed 2 years ago

dairyisscary commented 2 years ago

I have some code like this:

const [execute, { data, loading }] = useLazyQuery(query, {
  fetchPolicy: "network-only",
  nextFetchPolicy: "cache-first",
  notifyOnNetworkStatusChange: true,
});
const handleClick = () => execute({ variables: { something } });
return <button onClick={handleClick}>do it</button>;

I click the button (once) but see two queries in the network tab. If i click the button a second time, with new something, the query appears to only fire one more time, as expected

In my debugging, I found that this line is executing the query for the same variables and same options passed to useLazyQuery: https://github.com/apollographql/apollo-client/blob/76ad8a789a20a4962270649dfe5e5fbcfbf9c0fa/src/react/hooks/useQuery.ts#L215

for me, the second extra query has this:

currentWatchQueryOptions === {
  fetchPolicy: "standby"
  initialFetchPolicy: "network-only"
  nextFetchPolicy: "cache-first"
  notifyOnNetworkStatusChange: true
  query: {…}
  variables: { something }
};
// and
watchQueryOptions === {
  fetchPolicy: "network-only"
  nextFetchPolicy: "cache-first"
  notifyOnNetworkStatusChange: true
  query: {…}
  variables: { something }
}

Hopefully this is helpful and not just a red herring :)

benjamn commented 2 years ago

@dairyisscary Can you try npm i @apollo/client@beta to install version 3.7.0-alpha.2? That version includes #9666, which I think may help with this issue. If that solves your problem, then we will release 3.6.3 with the same changes.

dairyisscary commented 2 years ago

@benjamn thanks for getting back so quickly!

No, unfortunately, I can still reproduce on 3.7.0-alpha.2. Again, not sure if this is helpful at all but that !equal() check is not protecting the reobserve call in this case on the first re-render post-click.

benjamn commented 2 years ago

@dairyisscary Can you try putting the relevant code into a runnable reproduction? I'll keep trying things on my side, but a reproduction helps a ton.

dairyisscary commented 2 years ago

@benjamn https://github.com/dairyisscary/duplicate-lazy-query main branch has it

I struggled at first to reproduce it so I kept adding more and more of my configuration until I got it. it was the queryDeduplication: false on the Client constructor. sorry homie; completely forgot about this setting since its fire and forget. :)

I'm less certain this is a bug now but i will say on apollo 3.4.17 this does not duplicate the network request twice even with queryDeduplication turned off (I'm two releases behind, I never got to 3.5). if it is not a bug, what would you recommend benjamn? there doesn't appear to be a way to turn this on and off for an individual query -- I would turn it off for this particular query if it were possible.

benjamn commented 2 years ago

This is definitely something we (still) want to fix @dairyisscary! Thanks for the reproduction. 🙌

benjamn commented 2 years ago

@dairyisscary Figured it out (I think)!

benjamn commented 2 years ago

@dairyisscary This should be fixed if you run npm i @apollo/client@next (to get version 3.6.3)!

dairyisscary commented 2 years ago

amazing, seems to fix the issue in real app. thanks @benjamn!