reactjs React hook form和zod -使文件输入可选,并进行验证

jpfvwuh4  于 5个月前  发布在  React
关注(0)|答案(1)|浏览(88)

我有一个3个字段,文本框,文本区域和文件输入形式。文本框和文本区域是必填字段和文件输入是可选的。
我使用react-hook-form,zod和zodResolver。
我添加了一个方案,并设置文件输入为可选的模式,但当我提交的形式没有选择一个文件,其显示错误。
我想显示的文件输入验证只有当一个文件被选中(即文件输入是可选的)

'use client'

import { z } from "zod";
import { useForm } from 'react-hook-form'
import { zodResolver } from "@hookform/resolvers/zod";

export default function Form() {

    const MAX_FILE_SIZE = 2000000
    const ACCEPTED_IMAGE_TYPES = [
        'image/jpeg',
        'image/jpg',
        'image/png',
        'image/webp',
    ]

    const imageSchema = z.any()
        // To not allow empty files
        .refine((files) => files?.length >= 1, { message: 'Photo is required.' })
        // To not allow files other than images
        .refine((files) => ACCEPTED_IMAGE_TYPES.includes(files?.[0]?.type), {
            message: '.jpg, .jpeg, .png and .webp files are accepted.',
        })
        // To not allow files larger than 5MB
        .refine((files) => files?.[0]?.size <= MAX_FILE_SIZE, {
            message: `Max file size is 2MB.`,
        }).optional()

    const baseSchema = z.object({
        title: z.string().min(1, 'Title required').max(60, 'Maximum 60 characters.'),
        message: z.string().min(1, 'Message required.').max(120, 'Maximum 120 characters.'),
        image: imageSchema,
    });

    type FormValues = z.infer<typeof baseSchema>;
    const { register, handleSubmit, control, watch, reset, formState: { errors, isSubmitting } } = useForm<FormValues>({
        resolver: zodResolver(baseSchema),
    });

    //submit form
    const onSubmit = async (data: any) => {
        console.log(data);
    }

    return (
        <div className="mx-auto max-w-md container">
            <form onSubmit={handleSubmit(onSubmit)}>
                <div className="py-8 p-10 bg-slate-100 border-slate-200 rounded-xl border-2">

                    <div className="mb-6">
                        <label className="text-gray-700 font-bold" htmlFor="name">Title</label>
                        <input type="text" {...register('title')} className="w-full border border-gray-300 py-2 pl-3 rounded mt-2 outline-none" />
                        {errors.title && <div className="text-red-500">{errors.title?.message}</div>}
                    </div>

                    <div className="mb-6">
                        <div className="mb-6">
                            <label className="text-gray-700 font-bold" htmlFor="name">Message</label>
                            <textarea rows={4} {...register('message')} className="w-full border border-gray-300 py-2 pl-3 rounded mt-2 outline-none" />
                            {(errors as any).message && <div className="text-red-500">{(errors as any).message?.message}</div>}
                        </div>
                    </div>

                    <div className="mb-6">
                        <label className="text-gray-700 font-bold" htmlFor="name">Photo <span className="text-sm font-normal text-gray-700"> (optional)</span> </label>
                        <input type="file" {...register('image')} className="w-full border border-gray-300 py-2 pl-3 rounded mt-2 outline-none" />
                        {errors.image && <div className="text-red-500">{errors.image?.message?.toString()}</div>}
                    </div>

                    <button disabled={isSubmitting} type="submit" className="disabled:opacity-50 w-full mt-6 text-indigo-50 font-bold bg-indigo-600 py-3 rounded-md hover:bg-indigo-500"><span> Submit</span></button>
                </div>
            </form>
        </div>
    )
}

字符串

6uxekuva

6uxekuva1#

问题出在imageSchema中。我更新了图像架构,它按预期工作

const imageSchema = z.any().optional()
.refine(file => file.length == 1 ? ACCEPTED_IMAGE_TYPES.includes(file?.[0]?.type) ? true : false : true, 'Invalid file. choose either JPEG or PNG image')
.refine(file => file.length == 1 ? file[0]?.size <= MAX_FILE_SIZE ? true : false : true, 'Max file size allowed is 8MB.')

字符串

相关问题