Closed nicitaacom closed 8 months ago
Just by reading the provided error, it seems like there is an issue within the way you're calling the server action you're trying to use. Please make sure to check the docs which show some example uses and such.
https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
Just by reading the provided error, it seems like there is an issue within the way you're calling the server action you're trying to use. Please make sure to check the docs which show some example uses and such.
https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
And what I'm doing wrong?
I know how to use server actions
If I will call it like this - function will be never called
I tried to do it in different ways like this
Also it would be really really nice if you add some minimal example for your code here
Also I want to add additional context (because in error you see Cookies can only be modified in a Server Action or Route Handler
) - so I decided to do it in route handler
app/api/set-anonymous-id/route.ts
import { setAnonymousId } from "@/actions/setAnonymousId"
import { cookies } from "next/headers"
import { NextResponse } from "next/server"
export async function POST() {
cookies().set("anonymousId", `anonymousId_${crypto.randomUUID()}`)
return NextResponse.json({ status: 200 })
}
I tried await axios.post("/api/set-anonymous-id")
in layout.tsx
And got this error Error: An error occurred in the Server Components render but no message was provided
And I tired to do it in middleware.ts and got this error
AxiosError: There is no suitable adapter to dispatch the request since :
- adapter xhr is not supported by the environment
- adapter http is not available in the build
If I use await fetch("/api/set-anonymous-id")
then I get this error TypeError: Failed to parse URL from /api/set-anonymous-id
Also I want to add additional context (because in error you see
Cookies can only be modified in a Server Action or Route Handler
) - so I decided to do it in route handlerapp/api/set-anonymous-id/route.ts
import { setAnonymousId } from "@/actions/setAnonymousId" import { cookies } from "next/headers" import { NextResponse } from "next/server" export async function POST() { cookies().set("anonymousId", `anonymousId_${crypto.randomUUID()}`) return NextResponse.json({ status: 200 }) }
I tried
await axios.post("/api/set-anonymous-id")
in layout.tsxAnd got this error
Error: An error occurred in the Server Components render but no message was provided
And I tired to do it in middleware.ts and got this error
AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build
If I use
await fetch("/api/set-anonymous-id")
then I get this errorTypeError: Failed to parse URL from /api/set-anonymous-id
Relative urls don't work from the server. With regards to the rest, I can have a look later today into the root issue at hand.
@nicitaacom Below you'll find a demo repo which shows you two ways of updating cookies from the server.
https://github.com/JesseKoldewijn/next-cookie-setter-repro
One implementation uses a server action to update the cookie and the other uses fetch to fire a http POST request to a route handler which updates the cookie that way.
Also it would be really really nice if you add some minimal example for your code here
Server actions from as far as I understand and seen both in my own implementations and during mutliple events recently can be described like this. "Server actions are server-only functions you can pass to client components. When these functions are called they basically generate an rpc call towards your server which then responds with the return from your server action function."
This means that as far as I've seen and understand from the core concept of server action that they can only be called from the client, because they need to generate an rpc layer to function. If you try to call them from the server, you can basically call the same function without the "use server" directive because it gives you roughly the same result. Although in some instances the use server directive you actually prevent you from being able to use the given function from the server.
I want to give a disclaimer that the above is based on my personal experience and understanding of the given subject.
Hope this helped ya out.
@nicitaacom Below you'll find a demo repo which shows you two ways of updating cookies from the server.
https://github.com/JesseKoldewijn/next-cookie-setter-repro
One implementation uses a server action to update the cookie and the other uses fetch to fire a http POST request to a route handler which updates the cookie that way.
Thank you for example
I checked it and I see you can set cookie using client components only Yes you can do it through server action or route handler but anyway you do it from client component
I thought that its possible to set cookie on server
Some code
export default async function RootLayout({ children }: { children: React.ReactNode }) {
const ownerProducts = await getOwnerProducts()
const ToastProvider = lazy(() => import("./providers/ToastProvider"))
return (
<html lang="en" className={getCookie("darkMode") ?? "dark"}>
<body>
<Layout>{children}</Layout>
<ModalsQueryProvider ownerProducts={ownerProducts ?? []} />
<ModalsProvider />
<ToastProvider />
</body>
</html>
)
}
The main reason for that was set theme on server so user see no white (400ms) then dark screen
I figure out it using this
<html lang="en" className={getCookie("darkMode") ?? "dark"}>
Next.js let you getCookie() Next.js don't let you setCookie()
Next.js let you getCookie() Next.js let you setCookie()
This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.
Link to the code that reproduces this issue
https://github.com/nicitaacom/acc2-mvp-set-cookie-on-ssr
To Reproduce
demo - http://127.0.0.1:3000/
mvp - https://silver-space-cod-q956xqw99gr2947.github.dev/
github - https://github.com/nicitaacom/acc2-mvp-set-cookie-on-ssr
Variant 1
pnpx create-next-app@latest
app/actions/setAnonymousId.ts
import { cookies } from "next/headers"
export async function setAnonymousId() { cookies().set("anonymousId",
anonymousId_${crypto.randomUUID()}
) }app/layout.tsx
import type { Metadata } from "next" import { Inter } from "next/font/google" import { setAnonymousId } from "@/actions/setAnonymousId" import { getCookie } from "./utils/helpersSSR" const inter = Inter({ subsets: ["latin"] })
export const metadata: Metadata = { title: "TODO - rename project", description: "description", }
export default async function RootLayout({ children }: { children: React.ReactNode }) { const anonymousId = await getCookie("anonymousId") if (!anonymousId) { async function anonymousId() { "use server" await setAnonymousId() } await anonymousId() }
return (
) }
Error: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#cookiessetname-value-options at setAnonymousId (./app/actions/setAnonymousId.ts:14:61) at $$ACTION_0 (./app/layout.tsx:58:82) at RootLayout (./app/layout.tsx:32:151)
Error: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#cookiessetname-value-options at setAnonymousId (./app/actions/setAnonymousId.ts:14:61) at $$ACTION_0 (./app/layout.tsx:58:82) at RootLayout (./app/layout.tsx:32:151)
Which area(s) are affected? (Select all that apply)
Data fetching (gS(S)P, getInitialProps), Middleware / Edge (API routes, runtime)
Which stage(s) are affected? (Select all that apply)
next dev (local)
Additional context
No response