Reloading `initialData` after mutation
See original GitHub issueI’m having some trouble understanding the proper pattern when trying to update/revalidate data from one view/page that’s being mutated somewhere else. I’m using swr
in a Next.js project.
The scenario I’m facing is a fairly basic one:
/users
: A main page with a list of users. Fetches data using a/api/users
key./users/[username]
: A details page where you can edit attributes of a single user. Fetches data using a/api/users/[username]
key.
If you edit a user, changes to its attributes should be reflected back on the list when going back - which it did, until I introduced SSR via initialData
.
/users
page has a getServerSideProps
fetching all users on the list. Those are plugged into useSWR
as { initialData }
. This effectively avoids having to fetch users client side on first render, but makes it so it doesn’t refresh the list after editing a user entry: it always returns the original initialData
value.
Things I’ve tried:
-
Adding
revalidateOnMount: true
to theuseSWR
call. This solves the problem, but entirely defeats the purpose of passinginitialData
in as the exact same set of users is unnecessarily fetched twice: once SS fromgetServerSideProps
, once CS from the hook. -
Calling
mutate('/api/users')
from the edit page after successfully submitting the edit form. This would look like the natural solution to my issue. According to the docs, it should “broadcast a revalidation message globally to all SWRs with the same key” - but in my case, I found it doesn’t seem to do anything at all. -
Same as above, but calling
mutate('/api/users', async users => ...)
. However, theusers
array from the callback is alwaysundefined
for me. I would have expected the last set of fetched users from the list to be passed. Does this work when navigating between SSR’d pages? -
Same as above, but explicitly passing a new list of users with
mutate('/api/users', fetch('/api/users'))
. This works fine, but suffers from the same double fetching quirk as 1. Not to mention the incursion of a clear violation of SoC patterns.
So what’s the expected way to go about this? initialData
changes after a mutation and the server returns the correct value. However, it seems as though, swr
ignores new data after being set the first around and doesn’t “reload” or “reinitialize” it. While this might be intentional (mimic’ing things like useState
), how do I refresh my stale data without fetching the same more than once?
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:7 (3 by maintainers)
@nfantone RE: 2. in your list, the issue seems to be documented in https://github.com/vercel/swr/issues/751
If you call
mutate
on a key when there are no mounted components with auseSWR
for that key, thenmutate
is effectively a no-op. I ran into this and ended up manually clearing the cache for that specific key as well. There is no fetcher to go do the re-validation when amutate
is called in that case, but maybe it should be an option to do this cache clearing if there are no fetchers.@nfantone it’s not fully documented on readme yet, but you can take a look on the file https://github.com/vercel/swr/blob/master/src/cache.ts hope this is helpful for you