-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
feat: query cache provider #476
feat: query cache provider #476
Conversation
Nice! I would love to see the tests converted to use this. Thoughts? |
Sure I can update them if you like |
If it’s not too much trouble! 👍 |
fde53ef
to
66777c6
Compare
I've updated the tests. I sometimes get a warning about overlapping |
src/setFocusHandler.js
Outdated
@@ -9,7 +9,7 @@ const onWindowFocus = () => { | |||
const { refetchAllOnWindowFocus } = defaultConfigRef.current | |||
|
|||
if (isDocumentVisible() && isOnline()) { | |||
queryCache | |||
defaultQueryCacheRef.current |
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.
Hmmm. Does this feel funny to you? What if a user had multiple query caches in their app? How would they hook up to this? Should multiple caches be allowed?
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.
Yes it definitely felt funny! But as you can set up the focus handler outside of any sort of react context, it's very hard to determine which cache to use.
I used the same pattern as the config where there is a defaultConfigRef
- that the provider writes over. The focus handler actually uses the config ref as well so it's already a bit of a grey area...
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.
for reference https://github.com/tannerlinsley/react-query/blob/master/src/setFocusHandler.js#L9
Definitely open to cleaner solutions!
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.
Since this specific config value is "global", it kind of do make sense to use the latest one. For caches, maybe we should keep track of all active caches and update them all? I think that should make it possible to get rid of defaultQueryCacheRef
?
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've removed the defaultQueryCacheRef
in favour of a list of active caches
Nice work! This also relates to server rendering as per #461, if you want I can take a closer look and test it from that perspective tomorrow. 😄 |
@Ephem Awesome, since this is clearly cross-cutting, I'll let you test before proceeding. Also, just to confirm, this will all still be backwards compatible right? With the main goals being:
Confirm? |
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.
First of all, very nice work on this, I like the approach you are taking!
Just so my view on this PR is clear I think the goal should be to support explicit caches for testing, using different caches for different parts of the application/separate React roots and laying the foundation to build improved SSR support on top, but not change SSR behaviour in this PR.
Tests
- All internal tests are now updated to the new approach, which is great, but this also means the old approach is currently untested. Maybe add a few key tests targeting using the global cache, without a Provider?
- Maybe add a few tests using multiple caches/providers?
Query cleanup
I think an existing major issue right now is cache cleanup. I think the issues #432 and #460 are both related to this and also the act warnings in this PR. I think this could and should be fixed in this PR since the problem might actually become worse otherwise.
EDIT: This could just as well be done in a separate PR before this is merged.
Let me expand:
I'm pretty sure these problems stem from query timeouts not being cleared.
cache.clear = () => {
cache.queries = {}
notifyGlobalListeners()
}
The old cache clear function does not in any way remove the pending query timeouts for staleness etc. To get rid of these problems, I think calling cache.clear()
should also synchronously loop through all queries and remove all timeouts related to that query.
- If a user creates a cache manually with
makeQueryCache
, they own the cache and are responsible for callingcache.clear()
. - If
react-query
creates a cache, the library owns that cache and needs to clean it up if it is no longer used (for example, inReactQueryCacheProvider
).
Serverside rendering
This approach looks great from a SSR-perspective and this PR implements a key part of what is needed to improve that story. There is more work that is needed on top, but that should be done in a follow up and I see nothing that wouldn't be compatible!
src/queryCache.js
Outdated
} | ||
|
||
export function ReactQueryCacheProvider({ queryCache, children }) { | ||
defaultQueryCacheRef.current = queryCache || makeQueryCache() |
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.
If queryCache
is not provided, this will create a new queryCache on every render. Maybe this is also something to add a test for to avoid regression later?
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.
It should only create it once. That looks like it will be created on every render (if the queryCache isn't passed)
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've cleaned this logic up now so it tracks queryCache instances between renders
src/setFocusHandler.js
Outdated
@@ -9,7 +9,7 @@ const onWindowFocus = () => { | |||
const { refetchAllOnWindowFocus } = defaultConfigRef.current | |||
|
|||
if (isDocumentVisible() && isOnline()) { | |||
queryCache | |||
defaultQueryCacheRef.current |
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.
Since this specific config value is "global", it kind of do make sense to use the latest one. For caches, maybe we should keep track of all active caches and update them all? I think that should make it possible to get rid of defaultQueryCacheRef
?
the query cache now comes from a context, meaning users can easily override and control the cache being used inside their application
this commit does the follwing: track all active query caches added via the provider, handles mounting/unmounting if creating a cache, ensure we only do it once when unmounting an internally-created cache, make sure to clear it first setFocusHandler now loops through all of the currently-active caches
66777c6
to
84eb13c
Compare
84eb13c
to
3c8329d
Compare
I've added tests to show the global/default cache still works and a few tests for different caching scenarios The provider now tracks its queryCache value and if it's a self-created one, it cleans it up and removes it on unmount. If the cache is manually created, it's up to the creator to manage cleanup. I haven't touched on the in-depth cache cleanup (cancelling timeouts etc.) as I don't want to lose the focus of this PR. Happy to take this on separately though if nobody is working on it... |
Changes and tests looks great to me, really great work! I totally agree with addressing cache cleanup in a separate PR. Since it's possible that using a lot of Providers in tests could worsen the existing problems (more timeouts) I think it should probably be addressed before a release. |
Co-authored-by: Tanner Linsley <[email protected]>
🎉 This PR is included in version 1.5.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
the query cache now comes from a context, meaning users can easily override and control the cache being used inside their application
see #460
this is a basic use case of creating an isolated cache for testing
in component:
in unit test: