Next.js Discord

Discord Forum

Error: Cookies can only be modified in a Server Action or Route Handler.

Answered
Mugger Crocodile posted this in #help-forum
Open in Discord
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
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?
View full answer

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 perfect
You 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.