Next.js Discord

Discord Forum

Maintaining Client-Side Modal State with Server Action Revalidation in Next.js

Unanswered
Tomistoma posted this in #help-forum
Open in Discord
Avatar
TomistomaOP
I'm currently in the process of migrating a project from Next.js' traditional pages router to the new app router. As part of this migration, I'm aiming to transition my client-side API calls to server actions. However, I've hit a snag with one of my client components, specifically RedeemRewardButton. This component plays a crucial role in managing a reward redemption process, which involves guiding the user through a sequence of modals.

Workflow Description:
1. Initial Interaction: The user clicks on the RedeemRewardButton, which opens a confirmation modal.
2. Server Action: Upon user confirmation, the component triggers a server action (redeemRewardAction). This action makes an API call to my backend, processes the response, and returns a standard success or error response.
3. Page Revalidation Issue: The issue arises when I call revalidatePath('/') within my server action. This is intended to refresh user data (fetched server-side before page load) to reflect the newly redeemed reward and updated point balance.

Problem: The call to revalidatePath('/') causes a full page refresh, leading to the unintended closure of the success modal that should remain visible post-action.

Context:
- The data refresh is crucial as it updates the client with the latest reward data and point balance.
- I'm considering shifting this to a client-side API call. However, for consistency and the advantages of server actions (like direct access to environment variables and headers), I'm keen on using server actions across my project.
- Was previously using SWR for this.

Question:
How can I effectively refresh the stale data via my server action without disrupting the state of client-side modals? Is there a recommended approach in Next.js to achieve a seamless user experience where the data is updated in the background, but the client-side modal state is preserved?

Any suggestions or insights on this matter would be greatly appreciated. Thank you!

16 Replies

Avatar
Ray
Hi, have you tried creating the modal with intercepting routes?
https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes#modals
Avatar
TomistomaOP
No actually, haven't come across those, thanks for sharing! Have skim-read the documentation and will dig deeper shortly, but my immediate concern is that it might not be appropriate for "action" type modals that are triggered through business logic/flows. I wouldn't necessarily want someone to be able to directly link to a modal that requires prior confirmation for instance.
Avatar
Ray
the main point is the modal will keep open while you revalidating the data
Avatar
TomistomaOP
Yeah, I see that – might be a good solution for now at least. I'll give it a go. Still open to other options though! Previously I was handling these kind of state mutations with SWR, and instead of a full page refresh, I'd invalidate the data from my /users/authenticated end-point. That's what I'm trying to recreate here in a context where the data comes in from the server instead.
Avatar
Ray
other option would be use searchParams. eg. ?modal={true,false}
Avatar
TomistomaOP
That's a decent suggestion too. I think it's the shift in mindset around re-validating data that's catching me out more than anything here though. The modal issue itself is kind of a symptom of that. SWR mutations were pretty clear-cut in that respect.
Avatar
Ray
yeah you could do that but with intercepting routes or searchParams can reduce the amount of javascript to send to client
Avatar
Eric Burel
@Tomistoma I feel like it's a traditional issue of managing state while there might be page reloads
usually they are done in JS, when you mean a page refresh, you mean a new request/response roundtrip?
I need to double check but when JS is enabled the Server Actions tends to behave more like an SPA
it will receive an RSC payload instead of refreshing the page
=> this means you can store your modal state in a layout above the page
in a React context
because the "page refresh" is only a client one so it won't rerender the layout but just the page
Let me know if that's wrong I've never tested this way, cool use case
Avatar
TomistomaOP
@Eric Burel I'll DM you instead of polluting this thread 👍