Error: Cookies can only be modified in a Server Action or Route Handler.
Answered
Mugger Crocodile posted this in #help-forum
Mugger CrocodileOP
I am using a page.tsx file to check if the coupon is still available, and if not, removing it from cookies, but I am getting this error.
My page.tsx is not a client component and the actual function is in a 'use server' file, that's why I do not understand what is wrong with my code.
/page.tsx
My page.tsx is not a client component and the actual function is in a 'use server' file, that's why I do not understand what is wrong with my code.
/page.tsx
import { getCoinsRatio } from "@/lib/actions/settings.action";
import Selector from "./_components/Selector";
import type { Metadata } from "next";
import { Suspense } from "react";
import { cookies } from "next/headers";
import Coupon from "./_components/Coupon";
import { checkCoupons } from "@/lib/actions/coupon.action";
export const metadata: Metadata = {
title: "OhDeerCoins | Shop Coins",
description:
"A marketplace for buying LiveMe coins as easy as ordering a pizza.",
};
const Page = async () => {
await checkCoupons();
const coupon = cookies().get('activeCoupon')?.value
return (
<div className="my-[150px]">
<div className="mb-[200px] flex flex-col items-center justify-center gap-[25px] lg:mb-[350px]">
<p className="text-center text-[65px] font-bold lg:text-[96px]">
SHOP <span className="text-accent">COINS</span> FOR ALL
<br /> YOUR NEEDS
</p>
<p className="text-center text-[24px] font-medium text-accent lg:text-[32px]">
Orders completed 24/7
</p>
</div>
<Coupon activeCoupon={coupon}/>
<Suspense fallback={<div>Loading...</div>}>
<SuspensedSelector />
</Suspense>
</div>
);
};
export default Page;
const SuspensedSelector = async () => {
const rate = await getCoinsRatio(true);
const coupon = cookies().get("activeCoupon")?.value;
return <Selector coinsRatio={rate} coupon={coupon} />;
};Answered by Mugger Crocodile
so you mean I should use an useEffect() function in a client component to call the server action?
13 Replies
Mugger CrocodileOP
coupon.action.ts
"use server";
import { cookies } from "next/headers";
import { Coupon } from "../database/models/coupon.model";
import { revalidatePath } from "next/cache";
import { getUser } from "./auth.action";
export const checkCoupons = async () => {
const activeCouponCookie = cookies().get("activeCoupon");
if (activeCouponCookie) {
const activeCoupon = JSON.parse(activeCouponCookie.value);
const latest = await Coupon.findById(activeCoupon._id);
if (latest && new Date(latest.expirationDate) >= new Date()) {
return;
}
console.log('error here')
cookies().delete("activeCoupon");
}
};I get the error specifically from this checkCoupons function
I am also using this function
export const applyCoupon = async (code: string) => {
const coupon = await Coupon.findOne({ code });
if (!coupon || new Date() > new Date(coupon.expirationDate)) {
return {
success: false,
message: "Invalid coupon code",
};
}
cookies().set("activeCoupon", JSON.stringify(coupon), {
httpOnly: true,
secure: true,
});
revalidatePath("/shop-coins");
return {
success: true,
message: "Coupon applied successfully",
};
};, in the same file, but called from a client side component and everything woks perfectYou cant modify cookies inside page functions / server components, you will need to use a server action or route handler
@Exzotic You cant modify cookies inside page functions / server components, you will need to use a server action or route handler
Mugger CrocodileOP
But how do I call the server action if not from a page?
Because the actual function is on my server side
If you call a server action from a server component, it is just ran like a normal function called on the server
Mugger CrocodileOP
but my page.tsx should be a server component
Yeah, you cant modify cookies inside server components
By calling the function you are setting cookies while rendering the server component
@Exzotic By calling the function you are setting cookies while rendering the server component
Mugger CrocodileOP
so you mean I should use an useEffect() function in a client component to call the server action?
Answer
Mugger CrocodileOP
It actually worked, thanks. But now I'm a little more confused xD.
Maybe this page could help explain it: https://nextjs.org/docs/app/api-reference/functions/cookies#understanding-cookie-behavior-in-server-components