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

Avoid making network requests when skip is true #6752

Merged
merged 1 commit into from
Aug 1, 2020
Merged

Conversation

hwillson
Copy link
Member

When skip is set to true but other updated options have been passed into useQuery (like updated variables), useQuery will still make a network request, even though it will skip the handling of the response. This commit makes sure useQuery doesn't make unnecessary skip network requests.

Fixes #6670
Fixes #6190
Fixes #6572

@Titozzz
Copy link

Titozzz commented Jul 31, 2020

Great Job, we were just having that issue right now ❤️

@hwillson hwillson force-pushed the issue-6670 branch 2 times, most recently from 4486e89 to 96cbea3 Compare July 31, 2020 13:39
result: { data },
newData: () => ({ data: nextData })
})
mockSingleLink(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was behaving flakily due to its use of MockedProvider's newData function, which is kinda broken. I've adjusted the test to be more specific about the mocked requests it's working with, and added a few quick notes about the full workflow.

Copy link
Contributor

@jcreighton jcreighton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

Copy link
Member

@benjamn benjamn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with this conservative change/bugfix for 3.1.2, but I would really love to see the previous data delivered at some point, perhaps even in 3.2.0.

When skip is set to true but other updated options have been
passed into `useQuery` (like updated variables), `useQuery` will
still make a network request, even though it will skip the
handling of the response. This commit makes sure `useQuery`
doesn't make unnecessary `skip` network requests.

Fixes #6670
Fixes #6190
Fixes #6572
@hwillson hwillson merged commit 3a65ed4 into master Aug 1, 2020
@hwillson hwillson deleted the issue-6670 branch August 1, 2020 14:26
@macrozone
Copy link

I'm okay with this conservative change/bugfix for 3.1.2, but I would really love to see the previous data delivered at some point, perhaps even in 3.2.0.

tenor

Comment on lines +332 to +337
// NOTE: We no longer think this is the correct behavior. Skipping should
// not automatically set `data` to `undefined`, but instead leave the
// previous data in place. In other words, skipping should not mandate
// that previously received data is all of a sudden removed. Unfortunately,
// changing this is breaking, so we'll have to wait until Apollo Client
// 4.0 to address this.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@gtolarc
Copy link

gtolarc commented Aug 4, 2020

I used the logic to create a query by setting skip to true and use refetch only at the desired timing. After this patch, this logic no longer works with following error. Is this the intended situation?

TypeError: Cannot read property 'refetch' of undefined

@@ -227,6 +227,8 @@ export class QueryData<TData, TVariables> extends OperationData {
}

private updateObservableQuery() {
if (this.getOptions().skip) return;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, when the first option starts with skip: true, there is a problem that refetch is not ready and cannot be executed. How about changing the order as follows?

private updateObservableQuery() {
    // If we skipped initially, we may not have yet created the observable
    if (!this.currentObservable) {
      this.initializeObservableQuery();
      return;
    }

    if (this.getOptions().skip) return;

Copy link

@sirugh sirugh Aug 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that this isn't a bug, but isn't an initial state with skip: true what lazy query is for?

ie

const [runQuery, response] = useLazyQuery(myQuery);
useEffect(() => {
  if (!skip) {
    runQuery();
  }
}, [skip]);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there is no clear guidance on this in the official documents, a lot of users will think and use just like me. It is not easy to think of 'skip' affecting 'refetch' without any explanation.

And I can do it as you explained, but it has already become a strangely shaped code. And useLazyQuery's refetch function returns void, so we need to add more useEffect to use the response. The return value of useQuery's refetch is a promise, so you can use data directly with async/await. It's confusing why it was designed this way, but not all of these relationships seem clear and consistent.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just had exactly the same issue as you @gtolarc and was also using useQuery to get refetch because useLazyQuery returns void instead of a promise.

I'd be in favor of init the observable as well, as this change is quite breaking for a lot of people I guess 😕

@shrugs
Copy link

shrugs commented Aug 21, 2020

i've confirmed that updating to 3.1.3 in my project solves my skip-related issue

perhaps also solved apollographql/react-apollo#3492

@eugle
Copy link

eugle commented Aug 22, 2020

@shrugs Upgrade 3.1.3 does not solve the problem that SKIP is true and still requests the network

@FezVrasta
Copy link

FezVrasta commented Sep 16, 2020

Can confirm that this issue is still there in 3.1.4 and 3.2.0

@davidworkman9
Copy link

Also still seeing this on 3.2.0.

@FezVrasta
Copy link

For anyone having the same problem (everybody), here's a custom useQuery hook I'm using as a drop-in replacement to fix the issue:

import { useEffect } from 'react';
import { useLazyQuery } from '@apollo/client';

// The default Apollo's useQuery hook ignores the `skip` option if it's
// set to true the first time the hook is processed
export function useQuery(query, options) {
  const [execQuery, result] = useLazyQuery(query, options);

  useEffect(() => {
    if (options.skip !== true) {
      execQuery();
    }
  }, [execQuery, options.skip]);

  return result;
}

CarsonF added a commit to SeedCompany/cord-field that referenced this pull request Jan 21, 2021
CarsonF added a commit to SeedCompany/cord-field that referenced this pull request Jan 21, 2021
@bln-engaged
Copy link

This custom hook only seems to work if you don't need refetch or other useQuery capabilities.

For anyone having the same problem (everybody), here's a custom useQuery hook I'm using as a drop-in replacement to fix the issue:

import { useEffect } from 'react';
import { useLazyQuery } from '@apollo/client';

// The default Apollo's useQuery hook ignores the `skip` option if it's
// set to true the first time the hook is processed
export function useQuery(query, options) {
  const [execQuery, result] = useLazyQuery(query, options);

  useEffect(() => {
    if (options.skip !== true) {
      execQuery();
    }
  }, [execQuery, options.skip]);

  return result;
}

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