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 defaultContext property on ApolloClient #11275

Merged
merged 4 commits into from
Nov 2, 2023

Conversation

phryneas
Copy link
Member

@phryneas phryneas commented Oct 6, 2023

This would add a convenient way to address an issue that I've seen come up a lot recently:

People don't have an "obvious" way to change their authentication token outside the link chain, apart from recreating their ApolloClient instance, losing all cache contents in the process.

Our docs on authentication show using localStorage, which is not easily possible in Next.js, and might arguably be a bad practice in the first place.

What's left are global variables (again, not in Next.js) or scoping tricks, e.g. using a ref - but this is not really obvious.

Some recent related issues:
apollographql/apollo-client-nextjs#21
apollographql/apollo-client-nextjs#103
apollographql/apollo-client-nextjs#44

Also, half a dozen of Discord discussions.

To finish up the story, this would require an additional code change in the Next helper package to expose the client instance to parents of the NextApolloProvider, possibly using a callback or ref.

Checklist:

  • If this PR contains changes to the library itself (not necessary for e.g. docs updates), please include a changeset (see CONTRIBUTING.md)
  • If this PR is a new feature, please reference an issue where a consensus about the design was reached (not necessary for small changes)
  • Make sure all of the significant new logic is covered by tests

@phryneas phryneas requested a review from a team as a code owner October 6, 2023 09:10
@changeset-bot
Copy link

changeset-bot bot commented Oct 6, 2023

🦋 Changeset detected

Latest commit: c168bd2

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 Patch

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

@phryneas phryneas added this to the Release 3.9 milestone Oct 6, 2023
@phryneas phryneas self-assigned this Oct 6, 2023
Copy link
Member

@jerelmiller jerelmiller left a comment

Choose a reason for hiding this comment

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

Couple questions for you, but this looks good otherwise. I'd be happy to approve once you have a chance to respond!

expect(context).toEqual(
expect.objectContaining({
foo: { bar: "baz" },
a: { b: undefined, x: "y" },
Copy link
Member

Choose a reason for hiding this comment

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

Is the b: undefined here actually correct? Since its a shallow merge, I'd expect a to just be { x: 'y' } with the b key completely omitted. Would it be useful to make sure this test checks that? I think it passes right now because technically the value of b is undefined in both cases, but it feels misleading to show it here since this makes it look like it does some kind of deep merge.

Copy link
Member Author

@phryneas phryneas Oct 23, 2023

Choose a reason for hiding this comment

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

This is just my way of convincing jest to make sure that b isn't there or has no value.
If I tested for a: { x: "y" }, jest would also accept a a: { b: "still here", x: "y" }, as we are using objectContaining (the real context has a bunch of other values I don't care about and that I don't want to specify in this test)

);
});

it("`defaultContext` will be shallowly merged with context from `defaultOptions.query.context", async () => {
Copy link
Member

Choose a reason for hiding this comment

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

Actually this test brings up a good question:

What is the value of a defaultContext on its own rather than using defaultOptions.<query|watchQuery>.context? I'd like to better understand why someone couldn't just use defaultOptions.

Copy link
Member Author

@phryneas phryneas Oct 23, 2023

Choose a reason for hiding this comment

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

Just for completeness (we talked about this in person) - the defaultOptions would overwrite context instead of shallow-merging it, and also require people to save their token to three different places instead of having it in one central position (so a big DX improvement).

Copy link
Member

@jerelmiller jerelmiller left a comment

Choose a reason for hiding this comment

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

Chatted in person and the big change that this enables via a top-level defaultContext is that it is shallow merged with incoming context, where the current query/watchQuery/mutate default context is completely overwritten by incoming context. This was the crucial piece I missed in my initial review. Thanks for introducing this change!

@github-actions
Copy link
Contributor

github-actions bot commented Oct 23, 2023

size-limit report 📦

Path Size
dist/apollo-client.min.cjs 37.17 KB (+0.14% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/main.cjs" 43.64 KB (+0.12% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/main.cjs" (production) 42.11 KB (+0.13% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/index.js" 32.69 KB (+0.18% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/index.js" (production) 31.36 KB (+0.14% 🔺)
import { ApolloProvider } from "dist/react/index.js" 1.23 KB (0%)
import { ApolloProvider } from "dist/react/index.js" (production) 1.21 KB (0%)
import { useQuery } from "dist/react/index.js" 4.29 KB (0%)
import { useQuery } from "dist/react/index.js" (production) 4.11 KB (0%)
import { useLazyQuery } from "dist/react/index.js" 4.6 KB (0%)
import { useLazyQuery } from "dist/react/index.js" (production) 4.42 KB (0%)
import { useMutation } from "dist/react/index.js" 2.54 KB (0%)
import { useMutation } from "dist/react/index.js" (production) 2.53 KB (0%)
import { useSubscription } from "dist/react/index.js" 2.24 KB (0%)
import { useSubscription } from "dist/react/index.js" (production) 2.2 KB (0%)
import { useSuspenseQuery } from "dist/react/index.js" 4.29 KB (0%)
import { useSuspenseQuery } from "dist/react/index.js" (production) 3.73 KB (0%)
import { useBackgroundQuery } from "dist/react/index.js" 3.77 KB (0%)
import { useBackgroundQuery } from "dist/react/index.js" (production) 3.21 KB (0%)
import { useReadQuery } from "dist/react/index.js" 3 KB (0%)
import { useReadQuery } from "dist/react/index.js" (production) 2.95 KB (0%)
import { useFragment } from "dist/react/index.js" 2.1 KB (0%)
import { useFragment } from "dist/react/index.js" (production) 2.05 KB (0%)

@phryneas
Copy link
Member Author

phryneas commented Nov 2, 2023

Getting this in and putting another alpha out :)

@phryneas phryneas merged commit 3862f9b into release-3.9 Nov 2, 2023
6 checks passed
@phryneas phryneas deleted the pr/add-defaultContext branch November 2, 2023 10:14
Troyblants added a commit to Troyblants/apollo-client that referenced this pull request Nov 3, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 3, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants