我无法直接将 cookies 导入 Next JS 13 中的服务器操作。

huangapple go评论71阅读模式
英文:

I can't import cookies directly into server actions in Next JS 13

问题

I am working on a Next JS 13 project and I encountered an issue with server actions. Server actions can be used directly on form or button components, however, in my personal experience I found that you are most likely to define a server component in a separate file and import it into your client components. This works great until you want to access cookies or headers. If you try calling the headers() or cookies() function from next/headers you get the following error: Error: Invariant: Method expects to have requestAsyncStorage, none available. This only happens if the server action is in a separate file eg.

actions.js

"use server"
import { cookies } from "next/headers"

export default async function myFunction() {
   const token = cookies().get("my-token")
   return "done"
}

app/page.jsx

"use client"
import myFunction from "@/actions.js"

export default function Page() {
   async function doSomething() {
      await myFunction()
   }

   return <button onClick={doSomething}>my button</button>
}

Trying to run the following code resulted in the error above. I found a workaround which is posted as an answer below. Does anyone have an alternative solution that is a bit cleaner.

英文:

I am working on a Next JS 13 project and I encountered an issue with server actions. Server actions can be used directly on form or button components, however, in my personal experience I found that you are most likely to define a server component in a separate file and import it into your client components. This works great until you want to access cookies or headers. If you try calling the headers() or cookies() function from next/headers you get the following error: Error: Invariant: Method expects to have requestAsyncStorage, none available. This only happens if the server action is in a separate file eg.

actions.js

&quot;use server&quot;
import { cookies } from &quot;next/headers&quot;

export default async function myFunction() {
   const token = cookies().get(&quot;my-token&quot;)
   return &quot;done&quot;
}

app/page.jsx

&quot;use client&quot;
import myFunction from &quot;@/actions.js&quot;

export default function Page() {
   async function doSomething() {
      await myFunction()
   }

   return &lt;button onClick={doSomething}&gt;my button&lt;/button&gt;
}

Trying to run the following code resulted in the error above. I found a workaround which is posted as an answer below. Does anyone have an alternative solution that is a bit cleaner.

答案1

得分: 1

这是我实施的解决方法。

actions.js

"use server"

export default async function myFunction(cookies) {
   const token = await cookies.get("my-token")
   return "done"
}

app/layout.jsx

import { cookies } from "next/headers"

export default async function RootLayout({ children, params }) {
   
  params.cookies = {
    get: async function(cookie) {
      "use server"
      return cookies().get(cookie)
    },
    set: async function(cookie) {
      "use server"
      return cookies().set(cookie)
    }
  }

  return children
}

app/page.jsx

"use client"
import myFunction from "@/actions.js"

export default function Page({ params: { cookies }}) {
   async function doSomething() {
      await myFunction(cookies)
   }

   return <button onClick={doSomething}>my button</button>
}

类似的操作也可以用于headers

英文:

This is the workaround I implemented.

actions.js

&quot;use server&quot;

export default async function myFunction(cookies) {
   const token = await cookies.get(&quot;my-token&quot;)
   return &quot;done&quot;
}

app/layout.jsx

import { cookies } from &quot;next/headers&quot;

export default async function RootLayout({ children, params }) {
   
  params.cookies = {
    get: async function(cookie) {
      &quot;use server&quot;
      return cookies().get(cookie)
    },
    set: async function(cookie) {
      &quot;use server&quot;
      return cookies().set(cookie)
    }
  }

  return children
}

app/page.jsx

&quot;use client&quot;
import myFunction from &quot;@/actions.js&quot;

export default function Page({ params: { cookies }}) {
   async function doSomething() {
      await myFunction(cookies)
   }

   return &lt;button onClick={doSomething}&gt;my button&lt;/button&gt;
}

A similar thing can be done for headers.

答案2

得分: 1

截止到v13.4.6,此错误已得到修复。要升级到较新版本的Next JS,请参考此页面:https://nextjs.org/docs/pages/building-your-application/upgrading/version-13。

英文:

As of v13.4.6, this bug has been fixed. In order to update to a newer version of Next JS refer to this page: https://nextjs.org/docs/pages/building-your-application/upgrading/version-13.

huangapple
  • 本文由 发表于 2023年6月5日 01:07:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76401517.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定