Maintaining Client-Side Modal State with Server Action Revalidation in Next.js
Unanswered
Tomistoma posted this in #help-forum
![Avatar](https://cdn.discordapp.com/embed/avatars/1.png)
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
Workflow Description:
1. Initial Interaction: The user clicks on the
2. Server Action: Upon user confirmation, the component triggers a server action (
3. Page Revalidation Issue: The issue arises when I call
Problem: The call to
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!
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](https://cdn.discordapp.com/avatars/743561772069421169/3c5d689eee4459a24fc420063411c016.webp?size=256)
Ray
Hi, have you tried creating the modal with intercepting routes?
https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes#modals
https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes#modals
![Avatar](https://cdn.discordapp.com/embed/avatars/1.png)
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](https://cdn.discordapp.com/avatars/743561772069421169/3c5d689eee4459a24fc420063411c016.webp?size=256)
Ray
the main point is the modal will keep open while you revalidating the data
![Avatar](https://cdn.discordapp.com/embed/avatars/1.png)
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](https://cdn.discordapp.com/avatars/743561772069421169/3c5d689eee4459a24fc420063411c016.webp?size=256)
Ray
other option would be use searchParams. eg.
?modal={true,false}
![Avatar](https://cdn.discordapp.com/embed/avatars/1.png)
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](https://cdn.discordapp.com/avatars/743561772069421169/3c5d689eee4459a24fc420063411c016.webp?size=256)
Ray
yeah you could do that but with intercepting routes or searchParams can reduce the amount of javascript to send to client
![Avatar](https://cdn.discordapp.com/avatars/769111741098622976/a00ea6fb13337fd9ef76154f8e3cb990.webp?size=256)
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](https://cdn.discordapp.com/embed/avatars/1.png)
TomistomaOP
@Eric Burel I'll DM you instead of polluting this thread ðŸ‘