next.js: Importing server action from 'use client' component results in error when submitted.
Verify canary release
- I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
Platform: linux
Arch: x64
Version: #202204271406~1655476786~22.04~62dd706 SMP PREEMPT Fri Jun 17 16
Binaries:
Node: 18.16.0
npm: 9.5.1
Yarn: 3.5.0
pnpm: N/A
Relevant packages:
next: 13.4.0
eslint-config-next: 13.4.0
react: 18.2.0
react-dom: 18.2.0
Which area(s) of Next.js are affected? (leave empty if unsure)
No response
Link to the code that reproduces this issue
To Reproduce
- Go to codesandbox
- Click submit button
- Observe error
Describe the Bug
Having a component that has the directive 'use client'
, which then imports an action that has the directive 'use server'
, will result in an error stating that
Invariant: Method expects to have requestAsyncStorage, none available
When invoked from a form.
Expected Behavior
I expect the server action to work as expected, with both headers()
and cookies()
working.
Which browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 24
- Comments: 44 (11 by maintainers)
Commits related to this issue
- add test case for #49235 — committed to vercel/next.js by shuding a year ago
- Add test case for #49235 (#49488) This PR adds a test case for `headers()` and `cookies().set()` in Client Component imported actions. — committed to vercel/next.js by shuding a year ago
@shuding I installed that version and am still seeing the error when trying to write cookies
I was able to set up a codesandbox in which it works as expected: https://codesandbox.io/p/sandbox/awesome-johnson-o9i04r?file=%2Fapp%2Faction.ts
However: When using next-auth sadly this still breaks. In next-auth they do
which for some reason does not. I will open an issue in their repo, referencing this.
I have the same issue with Clerk.
import { currentUser } from "@clerk/nextjs/app-beta";
This should be fixed with #49470, a new canary will be cut soon.
Still hitting this issue with canary.4 and Clerk auth.
Having the same problem, which makes it so that next auth
getServerSessions
doesn’t work. There is a potential workaround for the time being but it’s really not nice: Instead of importing the function in the client component you can import it in a server component and pass it as a prop to the client component. Then the error goes away. But aside from the boilerplate that kind of defeats the purpose of it.+1
@borispoehland As described in the following document.
To call Server Actions that perform authentication internally from the Client Component, the header must be accessible. Therefore, import Server Actions in the parent Server Component and pass them to the target Client Component by prop drilling. Direct import of Server Actions from the Client Component will result in an error.
https://clerk.com/docs/nextjs/server-actions#with-client-components
This is incorrect.
startTransition
supports async transitions when you have server actions enabled (using experimental React).E.g. this is valid:
If you want to call
next-auth
’sgetServerSession
in a server action from a client component, I posted a workaround here that you can use until the bug is fixed.Should be good in
13.4.2-canary.2
!Same error “Invariant: Method expects to have requestAsyncStorage, none available” when access cookies in server actions which called by client component (triggered by onClick with startTransition). Access cookies in server actions used by server component (such as <form action={}) works fine.
For me too, thanks @EringiV3! However, I find it highly inconvenient to pass server actions via prop drilling. In some cases I had to pass it down 4 layers. I think in this case it‘d be more clean to just create an API route, do you agree? 😄
That fixed it for me, thnx ♥️
Does anyone know why it still ain’t working with Clerk.js?
Still causing in 13.4.2-canary.3
Ran into this as well, but the workaround didn’t seem to fix it for me
Passing the server action by action to a client component as described here: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions#props
Works flawlessly. 👍