Next.js Discord

Discord Forum

server action error

Unanswered
Cuvier’s Dwarf Caiman posted this in #help-forum
Open in Discord
Cuvier’s Dwarf CaimanOP
I am trying to use server actions and get formData but getting an error/squiggly line which states "The expected type comes from property 'action' which is declared here on type 'DetailedHTMLProps<FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>". What props should I have on my server action? I am using TS and Next 14. Thanks for your help.

47 Replies

Cuvier’s Dwarf CaimanOP
Thank gin for your response. It have defined formData as a prop as FormData. Is this the correct way to define it?
Cuvier’s Dwarf CaimanOP
Here is the server action code.
@Cuvier’s Dwarf Caiman Click to see attachment
"use server" on the top of your f ile
not inside the function
Cuvier’s Dwarf CaimanOP
Yes, apologies forgot to move that one out though still triggering the error. Any other thoughts?
Cuvier’s Dwarf CaimanOP
It is giving me a String is not assignable to promise String
@gin "use server" on the top of your f ile
Inside function is meant to work...
I just prefer top as its more clear and easier for file
@Cuvier’s Dwarf Caiman It is giving me a String is not assignable to promise String
Show where your using, as sever actions are always async and thus need to be awaited
Cuvier’s Dwarf CaimanOP
Hi risky. this where I am using it.
and whats the error on action
just screenshot it
@riský Inside function is meant to work...
yeah for inline functions
@Cuvier’s Dwarf Caiman Click to see attachment
this will not work cause this is a client component
that will work
how? explain
the type issue is prob it not returning void (the latest types version got more strict)
action={action} works in bot server or client
on server, the function must be "use server", but on client it can just be a function or a server action
he is obviously passing the server action directly to a client function
and that is a legit thing to do
how is that suppose to work without passing it down from a rsc or whatever
@riský and that is a legit thing to do
let me test it rn
you can call server actions as just another function in client also
@riský you can call server actions as just another function in client also
lol this is indeed working, since when was that a thing? xD
even @B33fb0n3 didnt think it was legit 🤣
-# i thought this was always a thing tho... idk when i first saw it
This is a reproduction of it: https://codesandbox.io/p/sandbox/8rl54k
@Cuvier’s Dwarf Caiman i figured out passing the formData from the action callback like this, will make the error go away
<form action={(formData: FormData) => clientSideHandler(formData)}>
           </form>
@B33fb0n3 This is a reproduction of it: https://codesandbox.io/p/sandbox/8rl54k
is that even the react that has server actions... like i think thats stable one
@riský is that even the react that has server actions... like i think thats stable one
oh yea, mb it's a repro with plain react
@gin <@1196462760570142832> i figured out passing the formData from the action callback like this, will make the error go away typescript <form action={(formData: FormData) => clientSideHandler(formData)}> </form>
Cuvier’s Dwarf CaimanOP
Hi gin, tried this one but still no luck? Anything else that I am missing? I managed to do this way succesfully before but now it is returning this error.
@riský Show where your using, as sever actions are always async and thus need to be awaited
Cuvier’s Dwarf CaimanOP
Here is the error in action.
yeah in your action, you are retuning a string, and action only wants it to be void... so you ether should return the string return or use it as a function if you want the value
-# (or (thefn as any) if you use it for other things and are wanting lazy fix like me)
@riský yeah in your action, you are retuning a string, and action only wants it to be void... so you ether should return the string return or use it as a function if you want the value
Cuvier’s Dwarf CaimanOP
Sorry I am bit confused with this. 😅 Are you able to provide a sample code for both of your solution above. Thanks!
Collared Plover
see if this helps;
const form = useForm<z.infer<typeof MenuItemSchema>>({
    resolver: zodResolver(MenuItemSchema),
    defaultValues: {
      name: "",
      description: "",
      category: "",
      basePrice: undefined,
      sizes: undefined,
      extraIngredientPrices: undefined,
      isItemAvailable: true,
    },
  });

  function onSubmit(values: z.infer<typeof MenuItemSchema>) {
    setError("");
    setSuccess("");

    startTransition(() => {
      createMenuItem(values)
        .then((data) => {
          if (data === null) {
            console.log("Received null data from the server.");
            setError("No response from the server.");
            return;
          }
          if (data?.error) {
            form.reset();
            setError(data?.error);
          }

          if (data?.success) {
            form.reset();
            setSuccess(data?.success);
          }
        })
        .catch(() => setError("Something went wrong!"));
    });
  }

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)}>
;
And here's the server action;
export async function createMenuItem(
  values: z.infer<typeof MenuItemSchema>,
): Promise<CreateMenuItemResponse> {
  console.log("Item creation process started with values:", values);

  // Validate form data using Zod schema
  const validatedFields = MenuItemSchema.safeParse(values);

  // If validation fails, return errors early
  if (!validatedFields.success) {
    console.log("Field validation failed:", validatedFields.error);
    return {
      errors: validatedFields.error.flatten().fieldErrors,
      message: "Validation failed: Invalid fields.",
    };
  }

  // Destructure validated data
  const {
    name,
    description,
    image,
    category,
    basePrice,
    sizes,
    extraIngredientPrices,
    isItemAvailable,
  } = validatedFields.data;

  const amountInCents = Math.round(basePrice * 100); // Ensure correct rounding

  // Optional: Check for existing menu item to prevent duplicates
  try {
    await connectToDatabase();

    const existingMenuItem = await MenuItemModel.findOne({ name });
    if (existingMenuItem) {
      return { error: "Item already exists!" };
    }

    // Create a new menu item
    await MenuItemModel.create({
      name,
      description,
      image,
      category,
      basePrice,
      sizes,
      extraIngredientPrices,
      isItemAvailable,
    });
    console.log("Item created successfully!");

    // Return success message
    return {
      success: "Item created successfully!",
    };
  } catch (error) {
    console.error("Failed to create menu item!", error);
    return { error: "Failed to create menu item!" };
  }
}
;
@Cuvier’s Dwarf Caiman
Cuvier’s Dwarf CaimanOP
Thanks The Geek. I think I have worked it now that there was a return in my server actions which triggers the error for soem reason.