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

Refactor useLazyQuery to reuse useInternalState and make execution function call reobserve instead of refetch #9564

Merged
merged 23 commits into from
Apr 5, 2022

Conversation

benjamn
Copy link
Member

@benjamn benjamn commented Mar 29, 2022

Building on #9563 and taking inspiration from #9459, this refactoring allows useLazyQuery to use the same InternalState machinery as useQuery (introduced in #9459), and fixes issue #9375 by making the execution function call reobserve (which respects the current fetchPolicy) instead of refetch (which always triggers a network request).

function useInternalState<TData, TVariables>(
export function useInternalState<TData, TVariables>(
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 function needs to be exported from this module so useLazyQuery can use it, but it is not exported publicly from the @apollo/client/react package.

Copy link
Contributor

@brainkim brainkim left a comment

Choose a reason for hiding this comment

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

Thanks for this Ben! We should roll all this up for the 3.6 release ASAP! Non-blocking thoughts added.

src/react/types/types.ts Show resolved Hide resolved
src/react/types/types.ts Show resolved Hide resolved
src/react/hooks/useQuery.ts Outdated Show resolved Hide resolved
@@ -466,7 +480,7 @@ class InternalState<TData, TVariables> {
};
} else if (
this.queryHookOptions.skip ||
this.queryHookOptions.fetchPolicy === 'standby'
this.watchQueryOptions.fetchPolicy === 'standby'
Copy link
Contributor

Choose a reason for hiding this comment

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

@benjamn I’m not 100% sure on why we read queryHookOptions over watchQueryOptions. You probably have explained this to me at some point and I just forgot.

Copy link
Member Author

Choose a reason for hiding this comment

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

The this.queryHookOptions object is just the raw QueryHookOptions passed to useQuery, which we save but do not modify/normalize. My intuition tells me we should prefer this.watchQueryOptions.fetchPolicy (as normalized in createWatchQueryOptions) because it has a better chance of matching up with this.queryHookOptions.skip, possibly even making it unnecessary to check this.queryHookOptions.skip here at all. I'm not sure that intuition is grounded in anything, though, so take with 🧂.

src/react/hooks/useLazyQuery.ts Outdated Show resolved Hide resolved
src/react/hooks/useQuery.ts Outdated Show resolved Hide resolved
@benjamn benjamn force-pushed the useLazyQuery-useInternalState branch from 172d08f to 89af070 Compare April 4, 2022 18:31
Comment on lines +134 to +139
/**
* Defaults to the initial value of options.fetchPolicy, but can be explicitly
* configured to specify the WatchQueryFetchPolicy to revert back to whenever
* variables change (unless nextFetchPolicy intervenes).
*/
initialFetchPolicy?: WatchQueryFetchPolicy;
Copy link
Member Author

@benjamn benjamn Apr 4, 2022

Choose a reason for hiding this comment

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

I don't love adding another optional field to WatchQueryOptions, but I truly do not expect anyone to need to use this field directly, and it helps us maintain the promise that skip: true is (more or less) synonymous with fetchPolicy: "standby", because it gives us a way to pass fetchPolicy: "standby" when skip: true without ending up stuck with initialFetchPolicy === "standby".

@benjamn benjamn changed the base branch from replace-useQuery-options-functions-with-options.defaultOptions to release-3.6 April 4, 2022 23:50
Comment on lines +249 to +255
// When skipping, we set watchQueryOptions.fetchPolicy initially to
// "standby", but we also need/want to preserve the initial non-standby
// fetchPolicy that would have been used if not skipping.
Object.assign(watchQueryOptions, {
initialFetchPolicy,
fetchPolicy: 'standby',
});
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 is where the initialFetchPolicy option comes in handy, because ObservableQuery can no longer use the fetchPolicy to infer the initialFetchPolicy if we use fetchPolicy: 'standby' to represent skip: true, so it's important to have another way to specify the initialFetchPolicy.

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