Server actions can't close over non-serializable values? #73395
-
|
(Relates to #49625) I have a server component that looks something like this // Server component
export default async function Foo({ someURL: URL, someFunction: () => any }) {
const submitAction = async (param: string) => {
"use server"
// Reference the props (=> capture them by closure)
someFunction(someURL)
}
return (
<div>Nothing here</div>
)
}Note there's no client component, no "use client" declaration involved anywhere in this story. After a number of these kinds of errors I have come to understand that server actions can't close over non-serializable values. Such as the URL and the function above. This is reinforced by the Closures and encryption docs which state
Have I got this right? Then firstly, this feels like quite the gotcha? The docs do state 'captured variables are sent to the client'. But as far as I've seen this is only in the context of some encryption discussion, not to stress - as is warranted - that all identifiers closed over by server actions must have serializable values. And the errors insist on referencing "Client Components" where there are none, which is confusing. Secondly, what alternative patterns do we have to make this work? I suspect that imported values (as opposed to local variables) can be referenced by server actions without issue. I.e. this import {someURL, someFunction} from 'someModule'
export default async function Foo() {
const submitAction = async (param: string) => {
"use server"
// Reference imported identifiers
someFunction(someURL)
}
return (
<div>Nothing here</div>
)
}(From my standpoint, passing component dependencies as props is better than importing them. This might be a minority view but I'm so attached to it that I'd rather 'use client' on everything rather than give up on props.) Are there some other alternative approaches? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
|
Server Actions are a React feature, and the React docs talks about these here: https://react.dev/reference/rsc/use-server#serializable-parameters-and-return-values But yeah, perhaps, this document, https://nextjs.org/blog/security-nextjs-server-components-actions#closures, should've also pointed out that, because they ought to be encryptable, they have to serializable... |
Beta Was this translation helpful? Give feedback.
-
|
Hey @icyJoseph thanks for your response. The React docs you've linked to seem to discuss arguments of server actions, not values that server actions close over. |
Beta Was this translation helpful? Give feedback.
Yeah that document is explicitly talking about, arguments passed, though not about captured closures, but it follows that everything concerning a server action, is sent to the client, to be used when the client invokes the server action.
Values are encrypted and such, and there's escape hatches, but since, ultimately a server action runs server side, in a different JS context/environment than the one that rendered the component.
I am not sure if this is where the error you've got starts, but that linked code, shows how the entire server action is replayed, within a fake scope, so to spe…