Next.js Discord

Discord Forum

Setting cookies with server actions

Unanswered
D Trombett posted this in #help-forum
Open in Discord
I have a page which needs to get some asynchronous data from the server before getting rendered so I'm exporting an asynchronous component from page.tsx like the following:
import { getAsynchronousData } from "@/app/actions";

const Page = async () => {
    const data = await getAsynchronousData();

    return (
            <div>
                <span>Data: {data.text}</span>
            </div>
        </main>
    );
};
export default Page;

Then in app/actions.ts I have defined the function which also may need to set a cookie in the client using cookies.set() like the following:
"use server";
import { cookies } from "next/headers";

export const getAsynchronousData = async () => {
    const auth = cookies().get("authorization")?.value;

    await asynchronousOperations();
    if (!auth) return { text: "You're not allowed!" };
    cookies().set("cookie", "data");
    return { text: "Your data" };
};

I would expect this to work like this:
1. The client opens the page
2. A request is made to the server which executes the getAsynchronousData function, set the cookies for the response and renders server side the page
3. The server sends the rendered page to the client
4. Everything works!

But instead I'm getting a Cookies can only be modified in a Server Action or Route Handler error which is quite weird since I'm modifying cookies in the server function. Also it works fine when I'm calling a server function for a form action for example...
So, what is the correct way to do this (or is it even possible to do)?

9 Replies

You are not using your action like an action
what you show is a method for getting data
within an RSC
this doesn't trigger a network request, your RSC will "just" get some data
a Server Action is used to react to a user interaction like clicking a button, submiting a form
internally, it fires a POST request to the server to handle this action
and there you can set cookies
what you are showing here is probably smth that should live in a middleware
I see what you mean, thanks, I managed to solve my issue