How to Pass Image Files with React Hook Form and Zod to Server Action?
Unanswered
Mackenzie River Husky posted this in #help-forum
Mackenzie River HuskyOP
How do you pass image files using React Hook Form and Zod to Server Action? I keep encountering this error:
Error: Only plain objects, and a few built-ins, can be passed to Server Actions. Classes or null prototypes are not supported.
I just can’t figure out what’s causing it. Here’s the Zod schema for the image:
image: z .instanceof(File) .refine( (file) => ACCEPTED_IMAGE_TYPES.includes(file.type),
My reacthookform setup:
const imageFile = new File([compressedFile], compressedFile.name, { type: compressedFile.type || file.type, });
setValue('image', file);
You can see the structure of an image file after compression in the picture.
By default, the compressedFile is a Blob, which is why I’m converting it into a File.
Any ideas on what format I should prepare the file in before submitting, so it’s accepted? I’d be incredibly grateful. This issue has caused me so much frustration. I’d be incredibly grateful for a working solution with zod, react-hook-form.
Error: Only plain objects, and a few built-ins, can be passed to Server Actions. Classes or null prototypes are not supported.
I just can’t figure out what’s causing it. Here’s the Zod schema for the image:
image: z .instanceof(File) .refine( (file) => ACCEPTED_IMAGE_TYPES.includes(file.type),
Only the following image types are allowed: ${ACCEPTED_IMAGE_TYPES.join(', ')}.
) .optional() .nullable(),My reacthookform setup:
const imageFile = new File([compressedFile], compressedFile.name, { type: compressedFile.type || file.type, });
setValue('image', file);
You can see the structure of an image file after compression in the picture.
By default, the compressedFile is a Blob, which is why I’m converting it into a File.
Any ideas on what format I should prepare the file in before submitting, so it’s accepted? I’d be incredibly grateful. This issue has caused me so much frustration. I’d be incredibly grateful for a working solution with zod, react-hook-form.
8 Replies
you can send files in the form of
File
type to server actions. can you console.log the Files at the exact moment before sending it to the server action?Mackenzie River HuskyOP
Unfortunately, I don’t fully understand what you mean exactly. I tried sending the file configured and converted as a File in Zod, but it gave me an error. I also attached an image showing the structure of the file when logged in the console. These are the details in my post.
In the meantime, I managed to get a working solution locally, but on the server, it throws an error:
HierarchyRequestError: Failed to execute 'appendChild' on 'Node': Only one element on document allowed.
Currently, I’m submitting two forms: one with the file (since it works locally this way) and another with the data. However, I’m starting to think that if nothing else works, I might need to split this into two separate actions: one to upload the file and return the data, and then another to submit everything again.
Here’s the submit section of my code:
Someone on Reddit also recommended using zod-form-data, but unfortunately, I haven’t been able to get it to work. If anyone can provide an example for that, it would be greatly appreciated!
In the meantime, I managed to get a working solution locally, but on the server, it throws an error:
HierarchyRequestError: Failed to execute 'appendChild' on 'Node': Only one element on document allowed.
Currently, I’m submitting two forms: one with the file (since it works locally this way) and another with the data. However, I’m starting to think that if nothing else works, I might need to split this into two separate actions: one to upload the file and return the data, and then another to submit everything again.
Here’s the submit section of my code:
action={async () => {
// REACT HOOK FORMS
const result = await trigger();
if (!result) return;
const { image, ...formData } = getValues();
// console.log('values: ', formData);
const formDataImg = new FormData();
if (image) formDataImg.append('image', image, image.name);
const { error, success } = await createDishCategory(formData, formDataImg);
if (error) {
toast.error(error);
} else {
toast.success(success);
reset();
setIsOpen(false);
}
}}
Someone on Reddit also recommended using zod-form-data, but unfortunately, I haven’t been able to get it to work. If anyone can provide an example for that, it would be greatly appreciated!
You can send image files into server actions as long as you send them in form of a File that is inside a
FormData
. You can see here https://x.com/alfonsusac/status/1867397579761496292Mackenzie River HuskyOP
That’s very kind of you to even make a video. Unfortunately, I’m using react-hook-form and zod for validation, and they don’t handle it as FormData in Next.js/React. So even if I write it as shown in the video, it still throws the error I mentioned.
even if you dont have access to FormData you can still pass File to server action
thats why im asking
can you console.log your
File
object before passing it to the server action? just to make sure RHF and Zod sucessfully process it before sending it to server