Would it be fine to call server actions during server commponent rendering?
I have a server action (marked with
"use server"). Would it be fine to call it during server component rendering (e.g. for setting cookies)? Would this work?
The code above does not work.
store.get("token") works normally because you are allowed to read cookies during a server component render, but
store.set("token", newToken) will not work because you are not allowed to set cookies during a server component rendering. So, the above example will not work.
A function exported from a
"use server" file only acts as a server action1 when it is called from a client interaction (i.e. triggered from the browser). It could be on a button click event, inside
useEffect, or inside the
formAction props.2 A server component render is not run on the browser, explaining why the function is not run as a server action.
As you've seen above,
cookies().set() does not work during a server component render. In fact, it's impossible3 to set cookies that way due to streaming. The server cannot update the response status and headers once streaming has started, which prevents you from setting cookies because that would require updating the
Set-Cookie header. Since server component rendering is streamed, you cannot set cookies (or set a custom header or set a custom status code) during a server component render.
Use middleware instead. It allows you to read and set cookies both in the request and in the response. So you can do something like
Beware though that
Middleware runs on the edge runtime, which is a restricted server-side runtime. Not all Node.js APIs are available. So you'll need
generateNewTokenFromOldTokento be compatible with the edge runtime.
In other words, things like
revalidatePath()would work normally inside that function. ↩
formActionprops are supported in server component, after the client-side React tree has been loaded they will be converted to client-side interactivity similar to the
Technically, if you call
cookies().set()before the first
Suspenseboundary, it would be theoretically possible to know the new cookies before streaming starts, so that
cookies().set()would work. However this is just a not-very-helpful special case and to my knowledge I don't think Next.js supports this edge case yet. ↩