nextjs How to use input type file in Form

47 min read

当你在使用React Hook Form与<Input type="file" />时,需要确保input是非受控的(uncontrolled)。以下是实现方法:

  1. 定义你的Zod Schema:

    import * as z from "zod";
    
    const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/jpg", "image/png", "image/webp"];
    const FormSchema = z.object({
        images: z
            .any()
            .refine(files => Array.from(files).every(file => file instanceof File), { message: "Expected a file" })
            .refine(files => Array.from(files).every(file => ACCEPTED_IMAGE_TYPES.includes(file.type)), "Only these types are allowed .jpg, .jpeg, .png and .webp"),
    });
    
  2. 实现Form组件:

    "use client"
    
    import { zodResolver } from "@hookform/resolvers/zod"
    import { useForm } from "react-hook-form"
    import * as z from "zod"
    
    import { Button } from "@/components/ui/button"
    import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"
    import { Input } from "@/components/ui/input"
    
    export default function FileUploadForm() {
        const form = useForm({
            resolver: zodResolver(FormSchema)
        });
    
        function onSubmit(data) {
            console.log(data);
        }
    
        return (
            <Form {...form}>
                <form onSubmit={form.handleSubmit(onSubmit)} className="w-2/3 space-y-6">
                    <FormField
                        control={form.control}
                        name="images"
                        render={({ field: { onChange, ...fieldProps } }) => (
                            <FormItem>
                                <FormLabel>Images</FormLabel>
                                <FormControl>
                                    <Input
                                        type="file"
                                        multiple
                                        {...fieldProps}
                                        onChange={(event) => onChange(event.target.files)}
                                    />
                                </FormControl>
                                <FormDescription>
                                    Upload images.
                                </FormDescription>
                                <FormMessage />
                            </FormItem>
                        )}
                    />
                    <Button type="submit">Submit</Button>
                </form>
            </Form>
        );
    }
    

在这个例子中,我们通过onChange事件处理文件输入,将文件数据传递给React Hook Form。这样可以确保input保持非受控状态,从而避免控制和非控制输入之间的冲突。