Next.js Discord

Discord Forum

How to pass image from form to action? Getting: Error: Only plain objects, and a few built-ins...

Answered
American Crocodile posted this in #help-forum
Open in Discord
American CrocodileOP
Error: Only plain objects, and a few built-ins, can be passed to Server Actions. Classes or null prototypes are not supported.


my code:
"use client";

...imports

...interface

export default function CreateWatchListForm({ handleClose }: any) {
  const [isLoading, setIsLoading] = React.useState(false);
  const [image, setImage] = React.useState<ImageType>();

  ...formSchema

  ...useForm

  const handleOnChange = (event: React.FormEvent<HTMLInputElement>) => {
    const target = event.target as HTMLInputElement & {
      files: FileList;
    };

    const img = new Image();
    img.src = URL.createObjectURL(target.files[0]);

    img.onload = function () {
      setImage({
        height: img.height,
        width: img.width,
        file: target.files[0],
      });
    };
  };

  const onSubmit = async (data: z.infer<typeof formSchema>) => {
    setIsLoading(true);

    let file;
    if (image?.file) {
      // Error happens here
      file = await uploadFile(image?.file);
    }

    // try {
    //   await createWatchListItem({
    //     ticker: data.ticker,
    //     notes: data.notes,
    //     imageWidth: image?.width,
    //     imageHeight: image?.height,
    //     imageFileId: file?.["$id"],
    //   });

    //   handleClose(false);
    // } catch (error) {
    //   console.log("Error creating transaction: ", error);
    // } finally {
    //   setIsLoading(false);
    // }
  };

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
        ...some inputs

        <div className="form-item">
          <FormLabel className="form-label">Image</FormLabel>
          <div className="flex w-full flex-col">
            <FormControl>
              <Input
                className="input-class"
                type="file"
                onChange={handleOnChange}
              />
            </FormControl>
          </div>
        </div>

        ...Button
      </form>
    </Form>
  );
}
Answered by joulev
you need to use a FormData

if (image?.file) {
  const form = new FormData();
  form.append("file", image.file);
  await uploadFile(form);
}

update uploadFile as needed
View full answer

3 Replies

American CrocodileOP
When I try JSON.parse(JSON.stringify(image?.file)) or JSON.parse(JSON.stringify(image)) I just get an empty object
@American Crocodile Error: Only plain objects, and a few built-ins, can be passed to Server Actions. Classes or null prototypes are not supported. my code: "use client"; ...imports ...interface export default function CreateWatchListForm({ handleClose }: any) { const [isLoading, setIsLoading] = React.useState(false); const [image, setImage] = React.useState<ImageType>(); ...formSchema ...useForm const handleOnChange = (event: React.FormEvent<HTMLInputElement>) => { const target = event.target as HTMLInputElement & { files: FileList; }; const img = new Image(); img.src = URL.createObjectURL(target.files[0]); img.onload = function () { setImage({ height: img.height, width: img.width, file: target.files[0], }); }; }; const onSubmit = async (data: z.infer<typeof formSchema>) => { setIsLoading(true); let file; if (image?.file) { // Error happens here file = await uploadFile(image?.file); } // try { // await createWatchListItem({ // ticker: data.ticker, // notes: data.notes, // imageWidth: image?.width, // imageHeight: image?.height, // imageFileId: file?.["$id"], // }); // handleClose(false); // } catch (error) { // console.log("Error creating transaction: ", error); // } finally { // setIsLoading(false); // } }; return ( <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> ...some inputs <div className="form-item"> <FormLabel className="form-label">Image</FormLabel> <div className="flex w-full flex-col"> <FormControl> <Input className="input-class" type="file" onChange={handleOnChange} /> </FormControl> </div> </div> ...Button </form> </Form> ); }
you need to use a FormData

if (image?.file) {
  const form = new FormData();
  form.append("file", image.file);
  await uploadFile(form);
}

update uploadFile as needed
Answer
American CrocodileOP
That worked passing data to the server! Thanks!