Next.js Discord

Discord Forum

revalidateTag in a server action in a suspended server component

Unanswered
Scrumplex posted this in #help-forum
Open in Discord
Avatar
I have a Server Component (wrapped in Suspense) that calls a Server Action that will revalidate a certain tag. This seems to cause a server side error like this:

[ Server ] Error: Route / used "revalidateTag foobar" during render which is unsupported. To ensure revalidation is performed consistently it must always happen outside of renders and cached functions. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering


The use case is this: A user clicks a link in an email, and we want to show them a loading page until the action has been completed. I assume I could refactor this to use loading.ts/loading.ts at some point.

I have a minimal reproduction here: https://codesandbox.io/p/devbox/unruffled-wilbur-dzvdyp?workspaceId=ws_DMWHE5EnmeHg9xHxT5di14

This worked some time ago. Is this unsupported now?

8 Replies

Avatar
server actions are supposed to be called from the client, not during server component rendering.

"use server";
export async function foo() {
  ...
}

in this instance,
"use client";
<button onClick={() => foo()}>
  Click me
</button>

it will act as a server action and revalidateTag will work, but in this instance,
async function ServerComponent() {
  await foo();
  // ...
}

it will just act as a regular javascript function and revalidateTag will not work because you cannot do
async function ServerComponent() {
  revalidateTag("foo");
}


why do you use a server action here in the first place and why do you need to revalidate anything here?
Avatar
I wrote a server action that updates a resource in an external application. Other parts of the code use Next Fetch to cache those resources and by updating them I want to revalidate the data. Currently this isn't an interactive action, but rather relies on a magic link sent in an email. Once the user visits the link I want to update the resource and revalidate cache
1. User clicks on magic link
2. Next.js shows a loading page (achieved by using Suspense around the (slow) Server Component)
3. The Server Component calls the slow API and revalidates cache
4. The Server Component renders a success/failure message
Avatar
hmm you can't revalidate something while rendering something else, so i think this is the simplest approach:

* just return the page immediately
* in the page, using useEffect or something similar, call the server action there
* when the server action resolves, set a state or something like that to remove the loading state
the "correct" approach here is to make it a route handler instead and run mutation+revalidation there, after that redirect the user to a success page – but this assumes the data update is fast and the approach is no longer usable when a loading screen is necessary
Avatar
I see. I personally don't like abusing useEffect for things like this. I might just change the magic link to require additional confirmation by clicking a button or something.

It seems like this was an intentional breakage in Next.js 15: https://github.com/vercel/next.js/pull/71093
Avatar
yeah well technically what you are doing is exactly a side effect during render. useEffect doesn't feel good here but you don't really have an alternative.
it's a legitimate use case, yes, but it is still a side effect during render – a mutation done inside a GET call