Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". #49625
-
I have a page with a server action but I'm getting the following error every time I try to submit the form: Error Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". page.tsx import config from "@/config";
import { findResource } from "../_utils";
import { redirect } from "next/navigation";
export default async function New({
params,
}: {
params: { resourceId: string };
}) {
const resource = findResource(config, params.resourceId);
const formFields = resource.fields.filter((field) => {
return field.id !== resource.primaryKey;
});
async function create(data: FormData) {
"use server";
if (resource.create) {
const item = await resource.create({ name: "Some", email: "Other" });
redirect(`/resources/${resource.id}/${item.id}`);
}
}
return (
<main>
<h1>New</h1>
<form action={create}>
{formFields.map((field) => (
<div key={field.id}>
<label htmlFor="">{field.name}</label>
<input type="text" name={field.id} />
</div>
))}
<button type="submit">Create</button>
</form>
</main>
);
} Version is 13.4.1 |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 7 replies
-
Found the answer, looks like it is not possible to use component props directly inside of the action so I had to pass the ID into a hidden input and after do the logic inside of the action. Here is what the final code looks like: import config from "@/config";
import { findResource } from "../utils";
import { Resource, ResourceValue } from "@/core";
import { redirect } from "next/navigation";
export default async function New({
params,
}: {
params: { resourceId: string };
}) {
const resource = findResource(config, params.resourceId);
return (
<main>
<h1>New</h1>
<Form resource={resource} />
</main>
);
}
const Form = ({ resource }: { resource: Resource }) => {
const formFields = resource.fields.filter((field) => {
return field.id !== resource.primaryKey;
});
async function create(formData: FormData) {
"use server";
const resourceId = formData.get("resourceId") as string;
const resource = findResource(config, resourceId);
if (resource.create) {
const item = await resource.create(
Object.fromEntries(formData.entries()) as ResourceValue
);
redirect(`/resources/${resource.id}/${item[resource.primaryKey]}`);
}
}
return (
<form action={create}>
{formFields.map((field) => (
<div key={field.id}>
<label htmlFor="">{field.name}</label>
<input type="text" name={field.id} />
<input type="hidden" name="resourceId" value={resource.id} />
</div>
))}
<button type="submit">Create</button>
</form>
);
}; |
Beta Was this translation helpful? Give feedback.
-
@BrunoQuaresma You should consider either re-opening this issue, because I came across the same thing, and I don't understand where the "Client Component" is, because none of my components are client, so technically speaking, I should be getting error, so I might just be an actual bug. Or maybe I'm just incorrect, and you've found a reason for it to think that the component is client, if so, could you help me understand it? |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
Found the answer, looks like it is not possible to use component props directly inside of the action so I had to pass the ID into a hidden input and after do the logic inside of the action. Here is what the final code looks like: