Error: Cookies can only be modified in a Server Action... but it is a server action?
Answered
David L. Bowman posted this in #help-forum
I cannot seem to delete all my cookies from a server action, I get the following error:
[ Server ] Error: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#options
// page.tsx
import { CreatePatientForm } from "@/components/CreatePatientForm";
import { deleteAllCookies } from "@/lib/next/deleteAllCookies";
export default async function Home() {
await deleteAllCookies();
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
// deleteAllCookies.ts
"use server";
import { cookies } from "next/headers";
export async function deleteAllCookies() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
}
Answered by B33fb0n3
when fetching your own endpoints inside a server component, you need to provide the full url from the api route instead of a relative url like you doing rn
In every case it's not recommended to fetch your own api routes. You want to delete all your cookies now. Why you would want to do that is unclear to me. It is not recommended. For more information read this: https://nextjs-faq.com/fetch-api-in-rsc
In every case it's not recommended to fetch your own api routes. You want to delete all your cookies now. Why you would want to do that is unclear to me. It is not recommended. For more information read this: https://nextjs-faq.com/fetch-api-in-rsc
20 Replies
when you calling your server action inside a server component, the server action will be translated to a normal function. And with that it's just a normal function.
You can only modify your cookies inside a server action or route handler. So do that and you will be good to go
You can only modify your cookies inside a server action or route handler. So do that and you will be good to go
Hmmm, that makes sense. Although, when I try to manipulate the cookies directly within the server component
/page.tsx
I get the same error:"use server";
import { CreatePatientForm } from "@/components/CreatePatientForm";
import { cookies } from "next/headers";
export default async function Home() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
yea, beeing inside a server component doesn't mean, that you are inside a server action or route handler.
You need to be inside a server action (call a server function from the client for example) or use a route handler
You need to be inside a server action (call a server function from the client for example) or use a route handler
I'm sorry, I don't understand. Could you tell me what I'm doing wrong? When I look at the documentation, it looks like I'm doing nearly the exact same thing.
import { CreatePatientForm } from "@/components/CreatePatientForm";
import { cookies } from "next/headers";
export default async function Home() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
Maybe it doesn't like my delete function.
you are right, you doing nearly exactly what's written down. There is one difference:
Server components: READ cookies (modifications are NOT allowed)
Server action or route handler: READ, MODIFY cookies (modifications are allowed)
What do you need to do?
Remove the deletion (modify) of your cookies.
Server components: READ cookies (modifications are NOT allowed)
Server action or route handler: READ, MODIFY cookies (modifications are allowed)
What do you need to do?
Remove the deletion (modify) of your cookies.
Okay, that makes sense. Then... how do I delete my cookies? When I try to call a server action like:
From within the
"use server";
import { cookies } from "next/headers";
export async function deleteAllCookies() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
}
From within the
/page.tsx
it doesn't work. Where am I supposed to call this function?I really appreciate your help btw.
don't use a server action here as it will be automatically translated to a normal function. Use a route handler instead
Okay, so... this may be the last thing, and I appreciate you teaching me.
Here's my
Here's my
/app/api/deleteAllCookies/route.ts
import { cookies } from "next/headers";
export async function DELETE(request: Request) {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
return new Response("Cookies Deleted", {
status: 200,
});
}
// page.tsx
import { CreatePatientForm } from "@/components/CreatePatientForm";
export default async function Home() {
await fetch("/api/deleteAllCookies", {
method: "DELETE",
});
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
when fetching your own endpoints inside a server component, you need to provide the full url from the api route instead of a relative url like you doing rn
In every case it's not recommended to fetch your own api routes. You want to delete all your cookies now. Why you would want to do that is unclear to me. It is not recommended. For more information read this: https://nextjs-faq.com/fetch-api-in-rsc
In every case it's not recommended to fetch your own api routes. You want to delete all your cookies now. Why you would want to do that is unclear to me. It is not recommended. For more information read this: https://nextjs-faq.com/fetch-api-in-rsc
Answer
Thank you, you taught me a lot of things, This works perfectly for me now.
I'm creating a demo app for a client, and I need them to reset their cookies every time they start the app.
Honestly, i should have just created a db.
Maybe this is still bad practice.
then it's the best to create a page.tsx for that that imports a client component with a button "clear all cookies". On the button click a server action will be called to delete all cookies.
As the server action is called from a client component, the server action works fine. It also doesn't happen on every request then
As the server action is called from a client component, the server action works fine. It also doesn't happen on every request then
I can do this, a better idea.
happy to help
i appreciated learning more about this though 🙂