Skip to content

Deprecate partial and ensure its correctness. Fix type of data in ApolloQueryResult #12333

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

Merged
merged 53 commits into from
Feb 5, 2025

Conversation

jerelmiller
Copy link
Member

@jerelmiller jerelmiller commented Jan 31, 2025

Closes #12332

This change aims to bring more consistency to the emitted results from the core API with the following changes:

  • Makes the partial flag a non-optional property that is now emitted with every ApolloQueryResult
  • Deprecates the partial flag. A followup solution will be provided with [4.0] Add a new status enum to ApolloQueryResult that describes the state of data #12344
  • Always sets a data property on the emitted result instead of omitting it when it would otherwise be undefined. This aligns the runtime behavior with the TypeScript type which specifies data as a non-optional property.
  • Updates ApolloQueryResult to specify data as TData | undefined to align it with the runtime behavior where an undefined result can be emitted from the core API.

@jerelmiller jerelmiller added this to the Release 4.0 milestone Jan 31, 2025
Copy link

changeset-bot bot commented Jan 31, 2025

🦋 Changeset detected

Latest commit: a8da500

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 Jan 31, 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: 5afc29be3d22d31968bd50dd

Copy link

pkg-pr-new bot commented Jan 31, 2025

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

commit: c7189bb

Copy link
Contributor

github-actions bot commented Jan 31, 2025

size-limit report 📦

Path Size
dist/apollo-client.min.cjs 33.47 KB (+0.02% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/main.cjs" 41.42 KB (+0.01% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/main.cjs" (production) 38.72 KB (+0.02% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/index.js" 36.14 KB (-0.02% 🔽)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/index.js" (production) 33.56 KB (+0.02% 🔺)
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.13 KB (+0.27% 🔺)
import { useQuery } from "dist/react/index.js" (production) 4.22 KB (+0.31% 🔺)
import { useLazyQuery } from "dist/react/index.js" 5.62 KB (+0.21% 🔺)
import { useLazyQuery } from "dist/react/index.js" (production) 4.7 KB (+0.34% 🔺)
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.44 KB (+0.16% 🔺)
import { useSubscription } from "dist/react/index.js" (production) 3.49 KB (+0.23% 🔺)
import { useSuspenseQuery } from "dist/react/index.js" 5.52 KB (+0.2% 🔺)
import { useSuspenseQuery } from "dist/react/index.js" (production) 4.18 KB (+0.22% 🔺)
import { useBackgroundQuery } from "dist/react/index.js" 5 KB (-0.2% 🔽)
import { useBackgroundQuery } from "dist/react/index.js" (production) 3.65 KB (-0.33% 🔽)
import { useLoadableQuery } from "dist/react/index.js" 5.08 KB (-0.25% 🔽)
import { useLoadableQuery } from "dist/react/index.js" (production) 3.73 KB (-0.29% 🔽)
import { useReadQuery } from "dist/react/index.js" 3.4 KB (-0.38% 🔽)
import { useReadQuery } from "dist/react/index.js" (production) 3.34 KB (-0.44% 🔽)
import { useFragment } from "dist/react/index.js" 2.01 KB (0%)
import { useFragment } from "dist/react/index.js" (production) 1.95 KB (0%)

@@ -1081,9 +1080,7 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`,
// because the query may be using the @nonreactive directive, and we want to
// save the the latest version of any nonreactive subtrees (in case
// getCurrentResult is called), even though we skip broadcasting changes.
if (lastError || !result.partial || this.options.returnPartialData) {
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 cache.diff is returning null for empty results or incomplete data, we no longer need this check as the value reported to this function is the correct value.

Copy link

netlify bot commented Jan 31, 2025

Deploy Preview for apollo-client-docs ready!

Name Link
🔨 Latest commit a8da500
🔍 Latest deploy log https://app.netlify.com/sites/apollo-client-docs/deploys/67a3ae0922528d0008b86365
😎 Deploy Preview https://deploy-preview-12333--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.

@@ -517,10 +517,7 @@ export class InternalQueryReference<TData = unknown> {

this.result = result;
this.promise =
(
result.data &&
(!result.partial || this.watchQueryOptions.returnPartialData)
Copy link
Member Author

Choose a reason for hiding this comment

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

Similarly, we don't need this check anymore since result.data will always be null if there is no data to report.

@@ -141,7 +141,7 @@ export type { QueryOptions as PureQueryOptions };
export type OperationVariables = Record<string, any>;

export interface ApolloQueryResult<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.

Eventually I'd like to make this type a bit smarter so that we can handle DeepPartial<TData> when complete is false, but I'll leave that to a separate PR.

Copy link
Member

Choose a reason for hiding this comment

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

👍

@@ -1345,7 +1345,7 @@ describe("client.watchQuery", () => {
const { data } = await queryStream.takeNext();
const fragmentObservable = client.watchFragment({
fragment,
from: data.currentUser,
from: data!.currentUser,
Copy link
Member

Choose a reason for hiding this comment

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

I know it's the correct thing to do, but this will be so annoying for our users :sad:

"@apollo/client": major
---

Fix type of `data` property on `ApolloQueryResult`. Previously this field was non-optional, non-null `TData`, however at runtime this value could be set to `undefined`. This field is now reported as `TData | undefined`.
Copy link
Member

Choose a reason for hiding this comment

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

Maybe we should call out here that this might need quite a lot of code adjustments?

Copy link
Contributor

@PowerKiKi PowerKiKi Mar 5, 2025

Choose a reason for hiding this comment

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

yeah, this will be a huge pain, and somehow counter-intuitive at first glance. But ultimately it is the way to go. I just wish we had a way to tell Apollo "I pinky-promise I will never use partial result in my entire project", and then the typing (and actual value) can never be undefined

Copy link
Member Author

Choose a reason for hiding this comment

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

@PowerKiKi I'm hoping that we can get #12350 in there which would help this situation a lot since we can narrow the type of data based on whether its empty, partial, or complete. We are bike shedding on the name, but will likely get this in there.

@@ -141,7 +141,7 @@ export type { QueryOptions as PureQueryOptions };
export type OperationVariables = Record<string, any>;

export interface ApolloQueryResult<T> {
Copy link
Member

Choose a reason for hiding this comment

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

👍

Comment on lines 2793 to 2794
complete: true,
partial: false,
Copy link
Member

Choose a reason for hiding this comment

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

This feels like a blocker for a 4.0 release to me.

Do we track somewhere that this has to be done as a follow-up before we can release a 4.0?

Copy link
Member Author

Choose a reason for hiding this comment

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

Created #12345 to call this out

@@ -733,7 +736,7 @@ export function toQueryResult<TData, TVariables extends OperationVariables>(
observable: ObservableQuery<TData, TVariables>,
client: ApolloClient<object>
): InternalQueryResult<TData, TVariables> {
const { data, partial, ...resultWithoutPartial } = result;
const { data, complete, partial, ...resultWithoutPartial } = result;
Copy link
Member

Choose a reason for hiding this comment

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

I'm actually a bit confused here (unrelated to this PR) - why do we have a returnPartialData option, but neither complete nor partial on the useQuery 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.

Agreed. As discussed in person, this will be done in a separate PR so we can add it to all the hooks.

@jerelmiller jerelmiller changed the title Change partial to complete and only set it when returnPartialData is true Deprecate partial and ensure its correctness. Fix type of data in ApolloQueryResult Feb 5, 2025
@jerelmiller jerelmiller merged commit 3e4beaa into release-4.0 Feb 5, 2025
40 checks passed
@jerelmiller jerelmiller deleted the jerel/partial-flag branch February 5, 2025 18:53
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 5, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants