-
Notifications
You must be signed in to change notification settings - Fork 1.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
RFC: Mutate multiple items #1946
Comments
Do you think it's better to only have the function instead of regex? And someone might prefer other glob patterns: And we only give the original key in the callback of mutate |
You can consult:https://swr.vercel.app/docs/advanced/cache
|
Currently, the global
mutate
API (imported directly from this package, or returned byuseSWRConfig()
) allows you to mutate a specific key in the SWR cache:Where
key
can be a valid SWR key argument (string | null | undefined | false | any[] | Record<any, any>
), or a function that returns a key.Proposal
In this proposal, we will make it also accept a filter function, and deprecate the case of function that returns a key. This extends the
mutate
API to filter through all the existing keys and mutate multiple of them in one call.This doesn't change the hook-returned
mutate
API (const { mutate } = useSWR(...)
).API and Use Case
Clear All
One typical use case is to clear or revalidate all keys, this can be done by passing a
() => true
function:Revalidate All
Some dashboards have the feature of switching the scope. Usually the API URL is still the same after switching the scope, but the authentication token might change and affect the final resource.
We used to handle this kind of things with token as the second argument in keys:
If we don't include
token
in the key, when switching the scope the resource won't refresh automatically and might cause the UI being outdated (still showing the previous scope).But then the pain comes when you want to mutate that resource:
mutate(['/api/user', ???])
. You'll have to know the token which identifies the resource. It somehow makes sense but in most cases the API is still the unique identifier of the resource here, as we can't have two tokens at the same time in one app instance.With the extended
mutate
API, we can solve it this way:We omit the
false
argument frommutate
, which defaults totrue
, meaning we want to refetch these resources again from the server. And the end user will see "old user → skeleton → new user".Mutate Only a Subset
Another common case is to only mutate/clear authentication-required resources, but keep the public ones. This can be done by using a filter function:
Also, it can be helpful to mutate resources that belong to the same category, such as a list of pages:
Open Questions
Simplicity
The most popular use case as far as we know is to clear all the cache, which doesn't look that easy and intuitive (
mutate(() => true, undefined, false)
). One way to simplify that is to add a shorthand API specifically for that case.useSWRInfinite
Apparently we need to skip special keys (where we keep the pages array, size and extra context) when doing a match mutate. But how do we tell the "pages state" to revalidate? Like updating the number of pages when you mutate a page to be
undefined
.Batching
Consider this common dependent request scenario:
If we do
mutate(() => true, undefined, true)
. And if the "mutate and revalidate" actions are batched (no render in between), then this will happen:Which causes an extra (*) revalidation that is unnecessary.
However, if we do the mutation and trigger the revalidation in another tick, we can avoid this problem but there might be other issues yet to explore.
Atomic
If we mutate multiple resources, do we think of them as multiple actions that are unrelated to each other, or one atomic action that affects multiple resources? For the latter we need to combine all revalidations and handle cache populations and error rollbacks after all of them, to keep data consistency.
Key Serialization
SWR accepts objects as the key. For example:
But then internally SWR serializes the object into a string. This makes it impossible to filter by key. One solution is to keep the original key object in cache with a special property name
_key
, and also addtoJSON
to keep the cache compatible with things likelocalStorage
. And then, the filter function will accept the original key value:However, it forces you to always check the type of the key first when doing a mutate action.
The text was updated successfully, but these errors were encountered: