Next.js Discord

Discord Forum

Refreshing RSC that has data which gets updated from another page

Unanswered
European sprat posted this in #help-forum
Open in Discord
European spratOP
I'd like to know how others are handling the following scenario:

- RSC fetches array of data from DB and shows a list of item names on the page (/items)
- Clicking on an item takes you to a page where you can edit the item name (/items/[id])
- Item name gets edited and an update API request from the client component is made completed (/api/items/[id])
- ????
- User navigates back to RSC which has the list of items (/items)
- EXPECTED: the item name shows the updated value

Currently, my RSC handles fetching but the listing of items is a client component which uses react-query to keep the data updated. There is nothing in this client component that has interactivity which requires it to be a client component.

The only other way I'm aware of accomplishing the goal of showing fresh data is using router.refresh() but this only really works when updating the data from the same page route. One way to use router.refresh() would be to have a useEffect which fires when the pathname changes but this seems quite inefficient (ie. on a page that is entirely RSC, I'd have to include a <Refresh/> client component just to trigger router.refresh() and this would be refreshing the RSC every time I hit the page, including when the page is loaded for the first time or browser reloaded).

I've looked at revalidatePath, revalidateTag, export const revalidate = 0 and any other of these cache related options but none of these apply to page routing when it's happening on the client.

Am I stuck with using client components to handling data refreshing or is there some other way to ensure the RSC is refreshed?

43 Replies

European spratOP
Anyone have any insight here?
Sloth bear
experiencing a similar conundrum:
https://discord.com/channels/752553802359505017/752647196419031042/1134557660486840362

I am calling router.push('url') from the client in next 13. This is being called after creating a new resource in the db. When i get directed to the page that should have the newly created item, I am getting a cached page. This page that should have the new item is server rendered. 

How can I force that cache miss on the push?


Obviously refreshing the page from a client component isn't optimal. :/
@joulev does it work if * you add `export const revalidate = 0` to the `url` page * or you call `revalidatePath("url")` when you create the new resource * or both?
European spratOP
looks like revalidatePath("url") works but only when used in a server action, it does not work for me when called from a route handler. export const revalidate = 0 seems to be irrelevant in this scenario
European spratOP
lol but it doesn't work when you navigate using browser back button
Sloth bear
@European sprat Can you revalidate the path from your route handler though?
Sloth bear
honestly that issue might warrent a github issue
@Sloth bear <@135324139648057344> Can you revalidate the path from your route handler though?
European spratOP
I cannot. I've also tried with and without my basePath
The no refresh from popstate still kills the whole thing for me and makes it so I have to stick with client fetching
Sloth bear
also, i just think the way cache is handled isnt optimal. Maybe its just my lack of understanding
btw-- i tried using export const revalidate = 0 on the page where the data is displayed and that didnt work.
https://nextjs.org/docs/app/building-your-application/data-fetching/revalidating#background-revalidation
This seems like the right pattern that should be implemented to pass a url to invalidate.

For my implementation, I would much rather pass an argument to the client router to force a cache skip like this:
router.push(`/explore/courses/${params.courseId}/units`, {
        skipCache: true,
      })
European spratOP
i've created a basic "tasks" app to show the different scenarios where data doesn't update to try and get some feedback on if what i'm doing is the wrong pattern or there's some other issue.

https://codesandbox.io/p/sandbox/github/frasergr/nextjs-revalidate/tree/main
@Sloth bear https://nextjs.org/docs/app/building-your-application/data-fetching/revalidating#background-revalidation This seems like the right pattern that should be implemented to pass a url to invalidate. For my implementation, I would much rather pass an argument to the client router to force a cache skip like this: router.push(`/explore/courses/${params.courseId}/units`, { skipCache: true, })
Havana
I can't find the #background-revalidation headline that you're linking to. Your suggestion is fine in case the current user is the only one editing the data. But consider this scenario:

1. User1 opens /items
2. User1 navigates to another page
3. User2 adds/modifies an item
4. User1 navigates back to /items without refreshing the page

User1 will still see an outdated version of /items. Or is there something I am missing?
Havana
Could it be that we need to fetch the data (e.g. using SWR) on the client side in addition to fetching from the database on server side as part of the pattern?
@Havana I can't find the #background-revalidation headline that you're linking to. Your suggestion is fine in case the current user is the only one editing the data. But consider this scenario: 1. User1 opens `/items` 2. User1 navigates to another page 3. User2 adds/modifies an item 4. User1 navigates back to `/items` without refreshing the page User1 will still see an outdated version of `/items`. Or is there something I am missing?
European spratOP
They changed that doc page yesterday which is why the link is missing.

What you describe is the situation we are facing.

From everything I can understand, calling revalidatePath("/items") when the add/modification happens should make it so new visits to /items will show the latest changes
But it doesn't seem to consistently work for me and it doesn't work when some forms of client side navigation happens (forward/back buttons on browser)
Sloth bear
^^ This running into this issue now. For some reason, when revalidating a page because new items have been added that should show, does not work. It seems to work on others. I have resorted to using full server actions to be able to do this.
Honestly, caching has become such a pain in the ass to deal with, writing giant builder functions to build urls that need to be invalidated on object creation. Its not optimal. Is there anyway i can turn off caching by default and make caching opt in?
wasting so much time on stuff that should just work imo.
Sloth bear
Thanks for the new link. That actually paints a better picture and confirms my hypothesis on how it works. Also we have terms now to explain what our problem is with xD

So I am calling revalidatePath on urls I have built within server actions. It is working on other routes, but for some reason, its not working on some.
European spratOP
yeah i have had spotty results too also noticed differences between dev and prod. it wasn't working in dev but prod build was fine
Sloth bear
I also have learned that router.back() will use the cached version no matter what revalidation you do.
European spratOP
afaik that's the same as pressing the browser back/forward buttons
and that's where i basically gave up on revalidation and using RSC. if it can't be refreshed on all page interactions when i want it to, i have to stick with client component and react-query keeping data in sync
i did hear someone mention you can use <a> for navigating and it will do a refresh (i'm guessing because it skips the client side router which is used with useRouter and <Link>?)
Sloth bear
yeah that is really frustrating. it should no matter what the client interaction is, invalidate the cache.
Sloth bear
When did they update the caching page? was that always there? So helpful
European spratOP
@Sloth bear I don't know how/why I didn't see this issue sooner https://github.com/vercel/next.js/issues/42991
Seems to describe everything I've been fighting with. Would have been nice if this was sorted before 13.4 or there was a clear indication and documentation about the behavior
i think it is probably the same as using an <a> but sounds like window.location.href will force the full refresh of the page
there is hope! i guess i'll stop banging my head against the wall trying to "make it work" and just wait
Sloth bear
YAY!
European spratOP
Not a good sign...
@European sprat Not a good sign...
Sloth bear
Link to that post?
i did my part