Next.js Discord

Discord Forum

Cannot Modify Cookie Server-Side

Answered
Lesser Yellowlegs posted this in #help-forum
Open in Discord
Lesser YellowlegsOP
I'm attempting to simply delete cookies on the server side. I'm so incredibly confused by NextJS at this point as I was able to set/delete the cookie using the exact same method. I'm calling a server action via a server component. I can check to make sre its running on the server via the typeof window check below.

Can someone explain to me why this is throwing an error?

error Error: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#cookiessetname-value-options


export async function getActiveUser() {
  "use server";
  const client = await getServerFetchClient();
  const activeUserId = await getActiveUserId();

  console.log("IS SERVER SIDE => ", typeof window === "undefined"); // true

  if (!activeUserId) {
    cookies().delete("access-token");
    cookies().delete("refresh-token");
    return;
  }

  return activeUserId;
}
Answered by fuma
Yes,
For read-only: middlewares, server components
You can read the cookie, and redirect the users if they're unauthorized

For read-write: route handlers, server actions
They're fired by the client, like pressing a "logout button" to clear auth cookies

And still want to remind you, server actions are used for forms like <form action={myAction}>, we won't use it for data fetching
View full answer

29 Replies

Your code is correct, can I see how do you calling the server action?
@fuma Your code is correct, can I see how do you calling the server action?
Lesser YellowlegsOP
export default async function RootLayout({
  children
}: {
  children: React.ReactNode;
}) {
  const activeUser = await getActiveUser();

  return (
    <div className="min-h-screen h-full flex flex-col">
according to this post, its by design. https://github.com/vercel/next.js/issues/51875

But I conceptually have no idea how to delete a cookie on the server now in Next13.
For now, you can't modify the cookies in a server component

Even if it is a server action, it is just a regular function on the server side. The server action must be invoked by the client in order to work

In your case, there're some alternatives like middleware or passing it to <form>.
Lesser YellowlegsOP
So is the hack to remove a cookie really to call it from a useEffect hook O_o???
It's not a hack if you want to remove the cookie during render
Lesser YellowlegsOP
You cannot even remove it from middleware.ts then eh?
You can use middleware too
Lesser YellowlegsOP
export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith("/sign-out")) {
    request.cookies.delete("access-token");
    request.cookies.delete("refresh-token");
    console.log("COOKIES => ", request.cookies.getAll()); // SAYS THEY ARE GONE BUT STILL THERE
    return NextResponse.rewrite(new URL("/", request.url));
  }
}


The cookie still exists
It needs a header instead of that, but firstly what are you trying to do?
Lesser YellowlegsOP
We have cookies that need to be invalidated based on sessions for different orgs. The code im sending is from a quick sandbox I created.

If a certain status code is returned, a cookie should be invalidated for the client.
So we have a server action that performs a GET. If a status code is returned indicating the cookie should be removed, the it should be deleted.
But it looks like I will have to play a dance with redirects to make that happen if I'm understanding correctly.
Why don't remove the cookies directly in that server action
Lesser YellowlegsOP
That is what the code in the top of the original post is trying to do
no, it's not how a server action be like. The code above is just calling the server action in a server component
Server actions are used for POST or DELETE for forms, if you want to do data fetching, consider using fetch on the client side.
Lesser YellowlegsOP
And if we want to fetch on the server to redirect if unauthorized?
Use a middleware will be more suitable in this case
Lesser YellowlegsOP
I see what you're saying I think. Break up the fetch and authorization logic. Authorization logic/redirect/cookie management in middleware and just data fetching in the server action?
Yes,
For read-only: middlewares, server components
You can read the cookie, and redirect the users if they're unauthorized

For read-write: route handlers, server actions
They're fired by the client, like pressing a "logout button" to clear auth cookies

And still want to remind you, server actions are used for forms like <form action={myAction}>, we won't use it for data fetching
Answer
Lesser YellowlegsOP
and if we want to fetch data server side on a server component? Don't use a "use server" function?
Yea, unless you hope it to be invoked by the client
Learn more about [Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions)
Lesser YellowlegsOP
export default async function Page() {
  const res = await fetch('https://...', { next: { tags: ['collection'] } })
  const data = await res.json()
  // ...
}


vs

export default async function Page() {
  const data = await fetchData();

  async function fetchData() {
    "use server";
    const res = await fetch("https://...", { next: { tags: ["collection"] } });
    const data = await res.json();
  }
  // ...
}


I guess we don't understand the fundamental difference between these two but we will read much more into it
we really really appriciate your help in understanding this from a bunch of guys coming from RoR
the first one is correct
the second one is an anti-pattern, it is not for data fetching
Lesser YellowlegsOP
Well we have some code to refactor it looks like lol. Like said, your help is legendary and thank you so very much
You can kiss me at #kudos :yay: