How to get, set and delete cookies in Next.js app router server components and route handlers

Published On

Cookies are essential part of them and have variety of application ranging from storing user preferences to stores auth tokens and all. So in this post we are going to explore How to get the cookies values and also how to set values and delete them in server component, client component and in api route handlers.

Here is the repo for this blog post.

Setup

I have this basic setup ready with only two routes and one api routes. So download it and run npm i to install all the dependencies.

Now let’s start with how to set and get cookies. We will start with server components.

Server Components

Server components allows you to perform actions without needing to make an api route. So you can basically fetch data directly into server components and also experimental support for handling form. We will set the auth token first using the experimental server actions then we will get the values

For setting cookie we will make use of server actions. So go to page.tsx and let’s firstly import the cookies function

import {cookies} from "next/headers";

So if you will set the login action it’s a simple server action. We are getting the email and password from input and we have to set cookies if the login is successful. I have not written authentication logic here.

So simply we will call the set method and pass the key value and optional options in which you can pass value to configure your cookie. Please refer to MDN docs for all options available.

cookies().set(key, value, {
   options...
});

Please note that you can perform this action in server actions and route handlers only. It will throw error even if it is a server component.

Here is the updated page.tsx

page.tsx
import { cookies } from "next/headers";

export default function Home() {
  const handleLogin = async (formData: FormData) => {
    "use server";

    const email = String(formData.get("email"));
    const password = String(formData.get("password"));

    // perform database operations and generate token

    cookies().set("auth-token", "some-auth-token-by-server-comp", {
      maxAge: 48 * 60 * 60, // valid for 2 days
      secure: process.env.NODE_ENV === "production",
      httpOnly: true,
    });
};

return (
  <main className="flex mx-3 flex-col items-center justify-center">
    <h1 className="my-5 text-center text-2xl font-bold">
      Getting and Setting Cookies in Next.js
    </h1>

      <div>
        <h2 className="mt-10 text-center text-3xl font-semibold">Set Cookie</h2>
        <form action={handleLogin}>
          <input
            type="email"
            className="bg-transparent px-2 py-2 block my-2 border-2 border-slate-800 rounded-md"
            placeholder="key"
            name="email"
          />
          <input
            type="password"
            className="bg-transparent px-2 py-2 block my-2 border-2 border-slate-800 rounded-md"
            placeholder="value"
            name="password"
          />
          <button className="bg-blue-600 rounded-md px-6 py-2 w-full text-white">
            Login
          </button>
        </form>
      </div>
    </main>

);
}

Open the console in your browser and open the Application tab then select the cookies tab. Hit the login button and you will see that cookies get stored.

Getting cookies value

Getting the cookies is very easy. Just call the cookies().get(name) method.

Please note that it will work perfectly in a server component (as opposed to cookies().set() method which can only be used in server action or route handler). You can perform this action without server action.

Here is updated page.tsx. I am simply displaying the cookie value if it exists and also using it one function. You can do more with it depending on the use case.

page.tsx
import { cookies } from "next/headers";

export default function Home() {
  const handleLogin = async (formData: FormData) => {
    "use server";

    const email = String(formData.get("email"));
    const password = String(formData.get("password"));

    // perform database operations

    // get the auth token

    cookies().set("auth-token", "some-auth-token-by-server-comp", {
      maxAge: 48 * 60 * 60,
      secure: process.env.NODE_ENV === "production",
      httpOnly: true,
    });
  };

  const fetchUserInfo = async () => {
    const authToken = cookies().get("auth-token")?.value;

    //perform further action
  };

  return (
    <main className="flex mx-3 flex-col items-center justify-center">
      <h1 className="my-5 text-center text-2xl font-bold">
        Getting and Setting Cookies in Next.js
      </h1>

      <div>
        <h2 className="mt-10 text-center text-3xl font-semibold">Set Cookie</h2>
        <form action={handleLogin}>
          <input
            type="email"
            className="bg-transparent px-2 py-2 block my-2 border-2 border-slate-800 rounded-md"
            placeholder="email"
            name="email"
          />
          <input
            type="password"
            className="bg-transparent px-2 py-2 block my-2 border-2 border-slate-800 rounded-md"
            placeholder="password"
            name="password"
          />
          <button className="bg-blue-600 rounded-md px-6 py-2 w-full text-white">
            Login
          </button>
        </form>
      </div>

      <div className="mt-5">
        <h2 className="mt-10 text-center text-3xl font-semibold">
          {" "}
          Cookie Value
        </h2>

        {cookies().get("auth-token")?.name && (
          <p className="mt-5 text-xl">
            {cookies().get("auth-token")?.name +
              ": " +
              cookies()?.get("auth-token")?.value}
          </p>
        )}
      </div>
    </main>
  );
}

You may want to delete some cookie based on action like logout you can do so easily by calling the delete method

...rest same no changes

const logout = async ()=>{
    // remove stored token
    cookies().delete("auth-token")
 }

Here is the video demonstrating the cookies actions server components

Client component

For getting and setting cookie in the client component we will make use of js-cookie library. So install the library first.

terminal
npm i js-cookie

# types if using typescript

npm i @types/js-cookie

Setting a cookie is very simple and easy. Firstly import the Cookie from “js-cookie” and just call the set method of it.

import Cookie from "js-cookie"
Cookie.set(key, value, {
  ...options
})

Here is updated client/page.tsx

client/page.tsx
"use client";
import Cookies from "js-cookie";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
export default function ClientPage() {
  const [isMounted, setIsMounted] = useState(false);

  // for hydration errors
  useEffect(() => {
    setIsMounted(true);
  }, []);
  const router = useRouter();
  const setCookie = async () => {
    Cookies.set("user-pref", "some-value-by-client-comp", {
      expires: 2,
    });
    router.refresh();
  };

  if (!isMounted) {
    return null;
  }
  return (
    <main className="flex mx-3 flex-col items-center justify-center">
      <h1 className="my-5 text-center text-2xl font-bold">
        Getting and Setting Cookies in Next.js (Client Component)
      </h1>

      <div>
        <h2 className="mt-10 text-center text-3xl font-semibold">Set Cookie</h2>

        <button
          onClick={setCookie}
          className="bg-blue-600 rounded-md px-6 py-2  mt-5 text-white"
        >
          Set Cookie
        </button>
      </div>
    </main>
  );
}

Use the Cookie.get(key) to get the cookie value

Here is updated client/page.tsx

client/page.tsx
"use client";
import Cookies from "js-cookie";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
export default function ClientPage() {
  const [isMounted, setIsMounted] = useState(false);

  // for hydration errors
  useEffect(() => {
    setIsMounted(true);
  }, []);
  const router = useRouter();
  const setCookie = async () => {
    Cookies.set("user-pref", "some-value-by-client-comp", {
      expires: 2,
    });
    router.refresh();
  };

  const getCookie = async () => {
    const cookieValue = Cookies.get("user-pref");
  };

  if (!isMounted) {
    return null;
  }
  return (
    <main className="flex px-3 flex-col items-center justify-center">
      <h1 className="my-5 text-2xl text-center font-bold">
        Getting and Setting Cookies in Next.js (Client Component)
      </h1>

      <div>
        <h2 className="mt-10 text-center text-3xl font-semibold">Set Cookie</h2>

        <button
          onClick={setCookie}
          className="bg-blue-600 rounded-md px-6 py-2  mt-5 text-white"
        >
          Set Cookie
        </button>
      </div>

      <div className="mt-5">
        <h2 className="mt-10 text-center text-3xl font-semibold">
          Cookie Value
        </h2>

        {Cookies.get("user-pref") && (
          <div className="flex items-center justify-center flex-col gap-3">
            <p className="mt-5 text-xl">
              {"user-pref" + ": " + Cookies?.get("user-pref")}
            </p>
          </div>
        )}
      </div>
    </main>
  );
}

Delete the cookie by calling Cookie.remove(key) to remove or delete the cookie.

Here is updated client/page.tsx

client/page.tsx
"use client";
import Cookies from "js-cookie";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
export default function ClientPage() {
  const [isMounted, setIsMounted] = useState(false);

// for hydration errors
useEffect(() => {
setIsMounted(true);
}, []);
const router = useRouter();
const setCookie = async () => {
Cookies.set("user-pref", "some-value-by-client-comp", {
expires: 2,
});
router.refresh();
};

const getCookie = async () => {
const cookieValue = Cookies.get("user-pref");
};

const removeCookie = async () => {
// remove the token from db
Cookies.remove("user-pref");
router.refresh();
};

if (!isMounted) {
return null;
}
return (

<main className="flex px-3 flex-col items-center justify-center">
<h1 className="my-5 text-2xl text-center font-bold">
Getting and Setting Cookies in Next.js (Client Component)
</h1>

      <div>
        <h2 className="mt-10 text-center text-3xl font-semibold">Set Cookie</h2>

        <button
          onClick={setCookie}
          className="bg-blue-600 rounded-md px-6 py-2  mt-5 text-white"
        >
          Set Cookie
        </button>
      </div>

      <div className="mt-5">
        <h2 className="mt-10 text-center text-3xl font-semibold">
          Cookie Value
        </h2>

        {Cookies.get("user-pref") && (
          <div className="flex items-center justify-center flex-col gap-3">
            <p className="mt-5 text-xl">
              {"user-pref" + ": " + Cookies?.get("user-pref")}
            </p>

            <button
              onClick={removeCookie}
              className="bg-blue-600 rounded-md px-6 py-2 w-fit mx-auto text-white"
            >
              Remove cookie
            </button>
          </div>
        )}
      </div>
    </main>

);
}

Route Handlers

Setting Cookies

There are two ways to set cookie. One is to use the next/headers. Here is the example

api/test/route.ts
import { NextResponse } from "next/server";
import { cookies } from "next/headers";

export async function GET(request: Request) {
  cookies().set("route_value", "some_value_api_routes", {
    expires: 48 * 60 * 60,
  });
  return NextResponse.json({ success: true });
}

The second method is using the standard Response object and passing cookies in the header

api/test/route.ts
export async function GET(request: Request) {
  // method 2
  const date = new Date();
  date.setTime(date.getTime() + 48 * 60 * 60 * 1000);

  return Response.json(
    { success: true },
    {
      headers: {
        "Set-Cookie": `route_value=some_value_api_routes; Expires=${date.toUTCString()};`,
      },
    }
  );
}

Getting the cookie is same as we did in server component. Just use the cookies().get(key) method

api/test/route.ts
import { cookies } from "next/headers";

export async function GET(request: Request) {
  const cookieVal = cookies().get("route_value")?.value;

  return Response.json({ cookieVal });
}

Here is the output

output of route handler

For deleting the cookie in next.js api route handlers just call the cookies.delete() method.

api/test/route.ts
import { cookies } from "next/headers";

export async function GET(request: Request) {
  cookies().set("route_value", "some_value_api_routes", {
    expires: 48 * 60 * 60,
  });
  const cookieVal = cookies().get("route_value")?.value;

  cookies().delete("route_value");
  return Response.json({ success: true });
}

Conclusion

In this post we explored how to get, set and delete cookies in Next.js server components, server actions, client components and API route handlers.

If you have any doubt, you can contact me via form or via the EverythingCS discord server