Skip to content
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

skip: true and skipToken behave differently with useSuspenseQuery #12059

Open
epmatsw opened this issue Sep 5, 2024 · 3 comments
Open

skip: true and skipToken behave differently with useSuspenseQuery #12059

epmatsw opened this issue Sep 5, 2024 · 3 comments

Comments

@epmatsw
Copy link

epmatsw commented Sep 5, 2024

Issue Description

I'm pretty sure this is a bug with skip: true, or at least skipToken behaves like I'd expect.

If you have a useSuspenseQuery that uses skip: boolean and toggles between true and false for that, it seems like sometimes the switch from true to false causes the query to skip the cache and suspend.

In the demo, you can quickly hit the button to toggle skipping on or off. Every once in a while, you can see the top one (skip: boolean) pop a suspend for a few frames, while the bottom one (skipToken) correctly re-reads from the cache.

Link to Reproduction

https://codesandbox.io/p/sandbox/lz67k5?file=%2Fsrc%2FApp.tsx%3A34%2C67

Reproduction Steps

No response

@apollo/client version

3.11.8

@jerelmiller
Copy link
Member

This is such an interesting one. Both skip: true and skipToken have almost the same code paths. It looks like the only difference is that we set some extra options for skip: true (not sure why to be honest). See how skipToken returns early while skip: true adds the extra options:

if (options === skipToken) {
return { query, fetchPolicy: "standby" };
}
const fetchPolicy =
options.fetchPolicy ||
client.defaultOptions.watchQuery?.fetchPolicy ||
"cache-first";
const watchQueryOptions = {
...options,
fetchPolicy,
query,
notifyOnNetworkStatusChange: false,
nextFetchPolicy: void 0,
};
if (__DEV__) {
validateOptions(watchQueryOptions);
}
// Assign the updated fetch policy after our validation since `standby` is
// not a supported fetch policy on its own without the use of `skip`.
if (options.skip) {
watchQueryOptions.fetchPolicy = "standby";
}

Other than this, both of these code paths rely on checking fetchPolicy: 'standby' in the downstream code which should avoid suspending (the __use hook is the thing that causes it to suspend):

const result = fetchPolicy === "standby" ? skipResult : __use(promise);

I'll have to dig into this further to understand where the difference is, but unfortunately won't have time to do so for a couple days. Thanks for raising the issue!

@jerelmiller jerelmiller added the 🔍 investigate Investigate further label Sep 5, 2024
@naman1608
Copy link

naman1608 commented Nov 15, 2024

Not sure but I think the options.skip check should also be moved with the skipToken check. It would help with the following -

  1. Consistency between both options.skip and skipToken
  2. There is no need to add notifyOnNetworkStatusChange and 'nextFetchPolicyas the query isn't being executed in the standby mode, so those lines seem redundant in the case ofoptions.skipastrue` also.

@jerelmiller I can put a PR if it makes sense. Although I see in the docs that options.skip is intended to be removed, so not sure if it be of help.

@jerelmiller
Copy link
Member

@naman1608 you're welcome to try a fix! I think moving the check for options.skip up to the same conditional as options === skipToken makes sense as a starting point. The one difference here is that variables is set in options with options.skip, so we might want to add a test case to make sure that changing variables while skip is true, then changing skip to false properly suspends and fetches with the right variables (does that make sense?).

We are preparing for our upcoming 3.12 release, so if you end up getting a fix in place, we'll look at adding that to a 3.12 patch release. No obligation though!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants