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 useQuery using InternalState class to simplify reasoning about state #9459

Merged
merged 47 commits into from
Mar 10, 2022

Conversation

benjamn
Copy link
Member

@benjamn benjamn commented Feb 25, 2022

This work began as a solution to issue #9204, incorporating the tests contributed by @jamesopti and @FritsvanCampen in #9407 and #9412. It snowballed into a more general refactoring of the useQuery hook, somewhat resembling the InternalState approach I used for useBackgroundQuery in #8783.

I feel like this approach has been productive so far, but before I spend more time on it, I wanted to share what I'm thinking (especially with @brainkim and @hwillson) in this draft PR.

I don't know if reviewing each commit is worthwhile, since some of the earlier commits are undone later, but I tried to do things incrementally, keeping tests passing with each commit, in case that's a helpful narrative.

This PR targets release-3.6, which seems appropriate for a refactoring of this size, but I am hopeful we can find a smaller/safer subset of the changes that we could ship in a 3.5.x patch release, so #9204 and related issues can be solved without waiting for v3.6.

Because this PR interacts so much with useQuery options handling, I've been holding off on #9223 and #9222 and some other issues until the dust has settled here.

FritsvanCampen and others added 30 commits February 25, 2022 13:44
I will revisit this approach to prevent repeated updates of unchanging
result properties (like obsQueryFields).
Removing result.partial when it's truthy defeats the whole purpose of
this (questionably necessary) field.
Follow-up/refinement to PR #9210.

Now that the createWatchQueryOptions function no longer defaults
watchQueryOptions.fetchPolicy to "cache-first" unconditionally (instead
defaulting to defaultOptions.watchQuery.fetchPolicy if defined), we can
let the merging of defaultOptions happen as it normally does, when
client.watchQuery(watchQueryOptions) is called later.
Using options as a useMemo dependency only happens to work here when
options is undefined. If options is an object created fresh every time
useQuery is called (as it often is), the useMemo version of this code
would produce a new watchQueryOptions object on every call.
This handful of test changes all seem defensible to me.
@benjamn benjamn added this to the Release 3.6 milestone Feb 25, 2022
Copy link
Member

@hwillson hwillson 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 @benjamn! At a high-level everything looks great, but I'll defer to @brainkim for a more in-depth seal of approval.

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.

A tidy and heroic effort. At a high-level, my main concerns with switching to a class is that, without some sort of mangling of the internal class properties, this will tick the size of the bundle upwards. Functions mangle much more nicely.

src/react/hooks/useQuery.ts Outdated Show resolved Hide resolved
src/react/hooks/useQuery.ts Outdated Show resolved Hide resolved
src/react/hooks/useQuery.ts Show resolved Hide resolved
src/react/hooks/useQuery.ts Outdated Show resolved Hide resolved
src/react/hooks/useQuery.ts Show resolved Hide resolved
src/react/hooks/useQuery.ts Outdated Show resolved Hide resolved
benjamn added a commit that referenced this pull request Mar 9, 2022
@benjamn benjamn force-pushed the useQuery-internal-state-ref branch from c9464c2 to d280d73 Compare March 9, 2022 22:53
@benjamn benjamn marked this pull request as ready for review March 9, 2022 22:57
@FritsvanCampen
Copy link
Contributor

Hi, I've had a chance to look at this.

It's good to see the original issue in #9204 is resolved.

I do still see a difference in behavior in this PR vs pre-3.5.x. Please see this PR: #9508. I've added two tests that test the exact frame output of useQuery. You can see that initially there is an extra unneeded frame. This frame was not present in 3.4.x. This is not as big of a problem as 9204 was, but it does create a little bit of inefficiency. I'm confident the unneeded frame can be removed by tweaking the implementation but I haven't looked into the details.

Similar tests could be added for useLazyQuery.

Is frame-testing something that you are interested in? Are you willing to incorporate the frame-tests to document the behavior of useQuery?

@benjamn
Copy link
Member Author

benjamn commented Mar 10, 2022

@FritsvanCampen Thanks for the review!

I'd like to hear more about frame testing, but let's continue in #9508?

In the meantime, I'll merge this PR and release another beta, so everyone can easily test it.

@benjamn benjamn merged commit 46e101b into release-3.6 Mar 10, 2022
@benjamn benjamn deleted the useQuery-internal-state-ref branch April 5, 2022 21:47
@benjamn benjamn restored the useQuery-internal-state-ref branch April 14, 2022 21:27
@apollographql apollographql locked as resolved and limited conversation to collaborators Feb 3, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants