-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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 suspenseCache as a lazy hidden property on ApolloClient #11053
Add suspenseCache as a lazy hidden property on ApolloClient #11053
Conversation
🦋 Changeset detectedLatest commit: 86a0ccd The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
size-limit report 📦
|
My thoughts: What I like:
What I don't like:
new ApolloClient({
defaultOptions: {
suspenseCache: {
autoDisposeTimeoutMs: xxx
}
}
}); Nitpicking on my solution here: Devs might not know what a "suspense cache" is when defining via I guess the question would be: do we feel this is a big enough improvement over the existing way to setup that we'd be ok making this "breaking change"? While I haven't heard complaints over the current style of creating the suspense cache, that doesn't mean others necessarily like it. I go back and forth and could go either way. I think if we can find a way to use Standard usage: no need to instantiate a suspense cache which provides the win in this PR: import { ApolloClient } from '@apollo/client';
<ApolloProvider client={client} />
// ...
useSuspenseQuery() // Works! Overriding the suspense cache to provide options. This avoids the indirection and makes it obvious how/where those options are used. import { ApolloClient, SuspenseCache } from '@apollo/client';
// instantiate and pass the instance to use this suspense cache
<ApolloProvider client={client} suspenseCache={new SuspenseCache(options)} /> My gripes are very small and nitpicky though. Nothing we can't solve with documentation. I'd be happy to find a way to make Thoughts on my thoughts 😆? |
Yeah, we could 100% drop that. I think as it's per-client either way, this is neither a plus nor a minus in the end? For me it was only important that we get a data structure that will get disposed of if it's not used any more, so the alternative would have been a global
Can't say anything against that :)
That sounds fine to me - I wasn't 100% sure if that would be the right place, so I went for the bucket approach, but in the end I don't care where these options live :)
That is actually my nitpick in the other direction: Most devs create a SuspenseCache without knowing what it is in the first place, so it's additional mental load - and they would need to read documentation on what it is either way.
We have to keep in mind that the audience currently installing the beta and the audience installing the final release later are probably a very different audience - I think if we can get rid of this additional mental load, that could be great.
We could also think about adding a // instantiate and pass the instance to use this suspense cache
<ApolloProvider client={client} suspenseCacheOptions={options} /> Writing this, I just noticed an additional benefit all this would have: We could remove the |
…suspenseCache-on-client
have no code except `getSuspenseCache` create a new SuspenseCache any more
export type CacheKey = any[]; | ||
import type { DocumentNode } from "graphql"; | ||
|
||
export type CacheKey = [query: DocumentNode, stringifiedVariables: string, ...queryKey: any[]]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that removing the client
from the CacheKey
didn't yield any type errors, so I cleaned this one up a bit.
@@ -14,18 +14,17 @@ interface ApolloCustomMatchers<R = void> { | |||
/** | |||
* Used to determine if the Suspense cache has a cache entry. | |||
*/ | |||
toHaveSuspenseCacheEntryUsing( | |||
client: ApolloClient<unknown>, | |||
toHaveSuspenseCacheEntryUsing: T extends ApolloClient<any> ? (( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will result in a TypeScript warning if toHaveSuspenseCacheEntryUsing
will be used on anything other than an ApolloClient
instance.
|
||
// TODO: remove export with release 3.8 | ||
// replace with | ||
// export type { SuspenseCache } from './SuspenseCache.js'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the future, there will not be any export of the SuspenseCache
class any more, not even Apollo-Client-internally.
Instead, we export the getSuspenseCache
(only for internal use, so it should not end up in any public entry points!) function.
@@ -43,7 +43,6 @@ import { useBackgroundQuery } from '../useBackgroundQuery'; | |||
import { useReadQuery } from '../useReadQuery'; | |||
import { ApolloProvider } from '../../context'; | |||
import { QUERY_REFERENCE_SYMBOL } from '../../cache/QueryReference'; | |||
import { SuspenseCache } from '../../cache'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests are now completely unaware of the "implementation detail" SuspenseCache
, apart from those using the toHaveSuspenseCacheEntry
matcher - and those are also not aware of any class called SuspenseCache
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉 I'm very happy with this change and I think our users will love this. I'm very glad we were able to making the suspense cache a transparent thing for users. Thanks for putting this together!
This is just an experiment I had in mind and wanted your feedback on @jerelmiller and @alessbell .
This removes
SuspenseCache
from theProvider
options, and instead creates aSuspenseCache
the first time it is requested byuseSuspenseCache
. It will be saved as a property on theApolloClient
instance, so those two instances will always be tied together (probably the biggest drawback I could see, but at the same time I would not expect people to decouple them).Configuration options can be passed in as part of the
ApolloClient
configuration:Note that the
ApolloClient
itself has no knowledge of any of that and is still pure "non-React".WDYT?
(I'm perfectly fine to trash this, I just wanted to give it a quick try :) )