set cookie in server action is not working despite the official docs #67709
Replies: 4 comments 4 replies
-
Could you reproduce it? or Could you give your code calling server action? This is my try. I change In // layout.tsx
'use client';
import './globals.css';
import { createEventLocaleCookie } from '@/actions';
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang='en'>
<body>
{children}
<button type='button' onClick={() => createEventLocaleCookie('ko')}>
set cookie
</button>
</body>
</html>
);
} // server actions as you did
"use server"
import { cookies } from "next/headers";
export async function createEventLocaleCookie(value: string) {
cookies().set("myLocale", value);
} |
Beta Was this translation helpful? Give feedback.
-
From what I am reading, you are calling your server action, as you render, in the body of the root layout, right? You are breaking the server action usage with that. A server action is a way for the client, to invoke a function in the server. When you call the server action, within a server component, you are essentially doing a no-op, in terms of server actions, and just calling a plain function. And, setting cookies, are you render a server component is not possible, because of streaming. |
Beta Was this translation helpful? Give feedback.
-
I was trying to use React Hook Form with server actions when I encountered the following error: " To resolve this, I found that I can use cookies inside a server action by wrapping the import { startTransition, useActionState } from "react";
const [state, formAction, isPending] = useActionState(
loginAction,
loginFormActionState,
);
const { control, handleSubmit } = useForm<LoginFormValues>({
resolver: zodResolver(loginFormSchema),
defaultValues: {
...loginFormDefaultValues,
...state?.fields,
},
});
<form
action={formAction}
onSubmit={handleSubmit((_, event) => {
startTransition(() =>
formAction(new FormData(event?.target as HTMLFormElement)),
);
})}
className="flex w-full flex-col gap-4"
>
{children}
</form>
// action.tsx
"use server";
export async function loginAction(
_prevState: LoginFormActionState,
formData: FormData,
) {
const parsed = loginFormSchema.safeParse(Object.fromEntries(formData));
if (!parsed.success) {
return {
fields: {
email: "",
password: "",
},
message: "Invalid username or password",
};
}
const authToken = '<your_auth_token>'
const cookieStore = await cookies();
cookieStore.set({
name: "auth_token",
value: authToken,
httpOnly: false,
secure: process.env.NODE_ENV === "production",
sameSite: "strict",
path: "/",
maxAge: 60 * 60 * 24 * 7,
});
revalidatePath("<path_to_revalidate>");
} @aestheticsdata you can give it a try, maybe it can help you with your case. |
Beta Was this translation helpful? Give feedback.
-
on my side this first option was failing then i resorted to only setting the expiration and not it works fine this failed to work in production
but this works well
my full code
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
I'm trying to call a server action from the RootLayout, and in the server action I'm trying to set a cookie like this (as explain in the official doc) :
And I get the error : "Cookies can only be modified in a Server Action or Route Handler",
But in the official doc I can read that we can set cookies in a server action : https://nextjs.org/docs/app/api-reference/functions/cookies#cookiessetname-value-options
Is the doc up to date ?
Additional information
No response
Example
No response
Beta Was this translation helpful? Give feedback.
All reactions