Sylv99
Sylv99

Reputation: 185

Unable to setcookies in app router in Next.js

I am learning next.js and the would like to set a cookie as in the code below.

The code returns an error: "Unhandled Runtime Error. Error: Cookies can only be modified in a Server Action or Route Handler."

I thought nextjs components were server components by default. I am using the app router.

I have googled, and have not managed to solve the issue.

Thank you.

import {cookies} from "next/headers";

function doit() {

    return new Promise<string>((resolve, reject) =>
    {
      setTimeout(
        ()=>
        {
          resolve("doit");
        }, 2000);
    });
  }

  const Home: React.FC = async () => {
  
    let results:string = await doit();

    if(results=="doit")
    {
        cookies().set("done", "true")
    }

    return (
      <div>
        <h1>H1 text</h1>
       </div>
    );
  }
  
  export default Home;

Upvotes: 0

Views: 654

Answers (1)

wolfie00
wolfie00

Reputation: 565

As far as I am concerned the Next.js has some limitation. You are trying to set a cookie on the client side within a Next.js component. Next.js has certain restrictions on modifying cookies, and they can only be modified in a Server Action or Route Handler. You have to implement the Server Action/Route Handler then make a request to set the cookies.

import { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// Rest of implementation goes here
  let results: string = await doit();

  if (results === 'doit') {
    res.setHeader('Set-Cookie', 'done=true');
  }

  res.status(200).json({ message: 'Success' });
}

function doit() {
  return new Promise<string>((resolve, reject) => {
    setTimeout(() => {
      resolve('doit');
    }, 2000);
  });
}

That would be the api handler for request for Cookies. You can use fetch/axios to fetch the data from the actual Home component which you sent. Make sure of course to place this on the server-side, f.e some server which provides the responses of your requests.

import { useEffect } from 'react';
import axios from 'axios';

const Home: React.FC = () => {
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('/api/set-cookie');
        console.log(response.data);
      } catch (error) {
        console.error('Error setting cookie:', error);
      }
    };

    fetchData();
  }, []);

  return (
    <div>
      <h1>H1 text</h1>
    </div>
  );
};

export default Home;

Inside the useEffect you can implement logic for handling the obtained data, remember also that you should replace /api/set-cookies with your actual path.

This article should be helpful: https://maxschmitt.me/posts/next-js-cookies

Upvotes: 1

Related Questions