Next.js Discord

Discord Forum

Best way to handle file input with react hook from zod in nextjs

Unanswered
Sai-Kolli posted this in #help-forum
Open in Discord
Hi guys can some one suggest best way to handle file inputs with react-hook-form and zod i am using shadcn for ui components.

my requirement is allow user to upload multiple images and i want to include validation for that field and i want to upload this images to storage only after submitting the form instead of uploading when ever they added images

here is my zod schema
export const addProductSchema = z.object({ brandName: z.string().min(1).max(255), productName: z.string().min(1).max(255), description: z .string() .min(1) .max(255) .default( "lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, voluptatum! " ), price: z.coerce.number().min(1).max(1000000), discount: z.coerce.number().min(1).max(100), sizes: z.array( z.object({ size: z.string(), quantity: z.coerce.number(), }) ), images: z.instanceof(FileList), });

Here is My defaultValues for the useForm hook

images: new FileList(),


here is my FormField

<FormField name="images" control={form.control} defaultValue={form.getValues("images")} render={({ field }) => ( <FormItem> <FormLabel>Images</FormLabel> <FormControl> <Input multiple type="file" onChange={(e) => { const files = e.target.files; if (files) { form.setValue("images", files); } }} /> </FormControl> <FormMessage /> </FormItem> )} />



please help me with this

Thank you.

11 Replies

@Sai-Kolli Hi guys can some one suggest best way to handle file inputs with react-hook-form and zod i am using shadcn for ui components. my requirement is allow user to upload multiple images and i want to include validation for that field and i want to upload this images to storage only after submitting the form instead of uploading when ever they added images here is my zod schema > `export const addProductSchema = z.object({ > brandName: z.string().min(1).max(255), > productName: z.string().min(1).max(255), > description: z > .string() > .min(1) > .max(255) > .default( > "lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, voluptatum! " > ), > price: z.coerce.number().min(1).max(1000000), > discount: z.coerce.number().min(1).max(100), > sizes: z.array( > z.object({ > size: z.string(), > quantity: z.coerce.number(), > }) > ), > images: z.instanceof(FileList), > });` > > Here is My defaultValues for the useForm hook > images: new FileList(), > > > here is my FormField > > `<FormField > name="images" > control={form.control} > defaultValue={form.getValues("images")} > render={({ field }) => ( > <FormItem> > <FormLabel>Images</FormLabel> > <FormControl> > <Input > multiple > type="file" > onChange={(e) => { > const files = e.target.files; > if (files) { > form.setValue("images", files); > } > }} > /> > </FormControl> > > <FormMessage /> > </FormItem> > )} > />` > > > please help me with this > > Thank you.
I usually do this
const MAX_FILE_SIZE = 500000;
const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/jpg", "image/png", "image/webp"];

const RegistrationSchema = z.object({
  profileImage: z
    .any()
    .refine((files) => files?.length == 1, "Image is required.")
    .refine((files) => files?.[0]?.size <= MAX_FILE_SIZE, `Max file size is 5MB.`)
    .refine(
      (files) => ACCEPTED_IMAGE_TYPES.includes(files?.[0]?.type),
      ".jpg, .jpeg, .png and .webp files are accepted."
    ),
});
tq so much @Ray for helping and i like this approach but still i have a problem of resetting the field after the sumbission

 const form = useForm<AddProductSchemaType>({
    resolver: zodResolver(addProductSchema),
    defaultValues: {
      brandName: "",
      productName: "",
      description: "",
      price: 0,
      discount: 0,
      images: [],
      sizes: [
        { size: "S", quantity: 0 },
        { size: "M", quantity: 0 },
        { size: "L", quantity: 0 },
      ],
    },
  });

Here is the field

<FormField
          name="images"
          control={form.control}
          defaultValue={[]}
          render={({ field }) => (
            <FormItem>
              <FormLabel>Images</FormLabel>
              <FormControl>
                <Input
                  multiple
                  type="file"
                  onChange={(e) => {
                    const files = e.target.files;
                    if (files) {
                      form.setValue("images", files);
                    }
                  }}
                />
              </FormControl>

              <FormMessage />
            </FormItem>
          )}
        />

remaining fields working fine
onSubmit handler

const onSubmit = async (data: AddProductSchemaType) => {
    console.log("formData", data);
    alert(JSON.stringify(data));
    form.reset();
  };
you could create a ref for the form and use ref.current?.reset() after the action
I initialized useForm hook to form
reset method is from react-hook-form returned by useForm hook
ah ok then form.reset() should do it
did you mean the field get reset but not the image field?
yes bro all are resetting except that image field whatever the images we selected still remains same. only on refresh it was working
try form.setValue("images", []); after form.reset()