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

Add a dataState enum to ApolloQueryResult #12350

Open
wants to merge 35 commits into
base: release-4.0
Choose a base branch
from

Conversation

jerelmiller
Copy link
Member

@jerelmiller jerelmiller commented Feb 6, 2025

Closes #12344
Closes #12345

Adds a new dataState enum returned from ApolloQueryResult that describes the state of the data property. ApolloQueryResult is now a discriminated union that better describes the value of data when in a particular state which provides additional type safety.

This new enum is now able to track whether the is waiting for additional chunks when used with @defer which can be useful to determine whether the full result has streamed in or not.

Copy link

changeset-bot bot commented Feb 6, 2025

🦋 Changeset detected

Latest commit: e05d975

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@apollo/client Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@svc-apollo-docs
Copy link

svc-apollo-docs commented Feb 6, 2025

⚠️ Docs preview not attached to branch

The preview was not built because the PR's base branch release-4.0 is not in the list of sources.

An Apollo team member can comment one of the following commands to dictate which branch to attach the preview to:

  • !docs set-base-branch version-2.6
  • !docs set-base-branch main

Build ID: 24473761fccaba737abe8ceb

Copy link

pkg-pr-new bot commented Feb 6, 2025

npm i https://pkg.pr.new/@apollo/client@12350

commit: e05d975

* - `complete`: `data` is a fully satisfied query result fulfilled
* either from the cache or network.
*/
dataState: "complete";
Copy link
Member Author

Choose a reason for hiding this comment

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

Let the bike shedding commence!

Copy link

netlify bot commented Feb 6, 2025

Deploy Preview for apollo-client-docs ready!

Name Link
🔨 Latest commit e05d975
🔍 Latest deploy log https://app.netlify.com/sites/apollo-client-docs/deploys/67a67e9ec9f42000086081b8
😎 Deploy Preview https://deploy-preview-12350--apollo-client-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Contributor

github-actions bot commented Feb 6, 2025

size-limit report 📦

Path Size
dist/apollo-client.min.cjs 33.55 KB (+0.22% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/main.cjs" 41.51 KB (+0.2% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/main.cjs" (production) 38.81 KB (+0.2% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/index.js" 36.24 KB (+0.24% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/index.js" (production) 33.64 KB (+0.23% 🔺)
import { ApolloProvider } from "dist/react/index.js" 1.26 KB (0%)
import { ApolloProvider } from "dist/react/index.js" (production) 1.24 KB (0%)
import { useQuery } from "dist/react/index.js" 5.18 KB (+0.86% 🔺)
import { useQuery } from "dist/react/index.js" (production) 4.26 KB (+0.86% 🔺)
import { useLazyQuery } from "dist/react/index.js" 5.65 KB (+0.54% 🔺)
import { useLazyQuery } from "dist/react/index.js" (production) 4.73 KB (+0.71% 🔺)
import { useMutation } from "dist/react/index.js" 3.62 KB (0%)
import { useMutation } from "dist/react/index.js" (production) 2.84 KB (0%)
import { useSubscription } from "dist/react/index.js" 4.45 KB (+0.23% 🔺)
import { useSubscription } from "dist/react/index.js" (production) 3.5 KB (+0.37% 🔺)
import { useSuspenseQuery } from "dist/react/index.js" 5.52 KB (-0.08% 🔽)
import { useSuspenseQuery } from "dist/react/index.js" (production) 4.18 KB (-0.08% 🔽)
import { useBackgroundQuery } from "dist/react/index.js" 5 KB (0%)
import { useBackgroundQuery } from "dist/react/index.js" (production) 3.65 KB (0%)
import { useLoadableQuery } from "dist/react/index.js" 5.08 KB (0%)
import { useLoadableQuery } from "dist/react/index.js" (production) 3.73 KB (0%)
import { useReadQuery } from "dist/react/index.js" 3.4 KB (0%)
import { useReadQuery } from "dist/react/index.js" (production) 3.35 KB (0%)
import { useFragment } from "dist/react/index.js" 2.01 KB (0%)
import { useFragment } from "dist/react/index.js" (production) 1.95 KB (0%)

| {
// Defer to the passed in type to properly type the `@defer` fields.
data: T;
dataState: "hasNext";
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not super in love with this name, but its been difficult to come up with something that doesn't sound the same as partial. The difference here is that partial is meant to describe a partial cache hit where some fields are missing, where hasNext is a @defer query that hasn't fully streamed in the full data set.

Other options considered:

  • streaming
  • pending

}
| {
// Defer to the passed in type to properly type the `@defer` fields.
data: T;
Copy link
Member Author

Choose a reason for hiding this comment

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

In the case of hasNext, I've left the T type alone. GraphQL Codegen will generate a type which includes a union on all deferred fields that handles the "missing" holes in the type.

The biggest downside to this is that the complete case also returns the type as-is which means the user will still have to check the deferred fields to ensure they are there to satisfy TypeScript. Ideally we could unwrap that type a bit, but this may prove to be challenging.

I welcome any thoughts here.

// Even though `data` didn't change, the `dataStatus` is updated to reflect
// that the full result has been stremed in so we expect another render
// value.
await expect(stream).toEmitApolloQueryResult({
Copy link
Member Author

Choose a reason for hiding this comment

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

Now that we are reporting the dataStatus enum with a proper value, I think it is necessary to emit another value that reports the dataStatus as complete, even though the data property itself didn't change since the deferred fragment was masked.

@jerelmiller jerelmiller requested a review from phryneas February 6, 2025 22:28
@jerelmiller jerelmiller marked this pull request as ready for review February 6, 2025 22:29
@@ -734,9 +736,9 @@ export function toQueryResult<TData, TVariables extends OperationVariables>(
observable: ObservableQuery<TData, TVariables>,
client: ApolloClient<object>
): InternalQueryResult<TData, TVariables> {
const { data, partial, ...resultWithoutPartial } = result;
const { data, partial, dataState, ...resultWithoutPartial } = result;
Copy link
Member Author

Choose a reason for hiding this comment

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

We will expose this property in a separate PR so we can add support for it to all hooks.

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

Successfully merging this pull request may close these issues.

2 participants