使用打字稿对同一个 react 表单组件使用两个 yup 模式

Use two yup schemas for the same react form component with typescript

提问人:Juan 提问时间:11/8/2023 更新时间:11/8/2023 访问量:20

问:

我有一个使用 yup 和 react hook 形式在 react 中创建产品的表单。同样的表单可以用来更新产品,所以我想也许我可以重用我声明的那个react功能组件来创建和更新。 我定义了以下接口和 yup 架构来处理验证,并声明在验证成功时我将使用的值:

export interface CreateProductFormValues{
    name: string
    description: string
    typeOfProduct: ProductType | ''
    stock: number
    price: number
    discount?: number | undefined
    file: File
}

export const CreateProductSchema = yup.object().shape({
    name: yup.string().required(),
    description: yup.string().required(),
    typeOfProduct: yup.mixed<ProductType | ''>().oneOf(['Medicine', 'Other']).required(),
    stock: yup.number().nullable().typeError('Stock must have a number').integer('Stock must be an integer number').required('Stock is required').positive('Stock must be a positive number'),
    price: yup.number().nullable().required().moreThan(0),
    discount: yup.number().positive().lessThan(100),
    file: yup.mixed<File>().required('An image is necessary').test('fileSize', 'The file is too large', (value) => {
        if(value instanceof File){
            return value && value.size <= 15*1024*1024;
        }
    })
    .test('fileType', 'Unsupported File Format', (value) => {
        return value && ['image/jpeg', 'image/png', 'image/jpg'].includes(value.type);
    })
});

export interface UpdateProductFormValues{
    name: string
    description: string
    typeOfProduct: ProductType | ''
    stock: number
    price: number
    discount?: number | undefined
    file?: File | undefined
}

export const UpdateProductSchema = yup.object().shape({
    name: yup.string().required(),
    description: yup.string().required(),
    typeOfProduct: yup.mixed<ProductType | ''>().oneOf(['Medicine', 'Other']).required(),
    stock: yup.number().nullable().typeError('Stock must have a number').integer('Stock must be an integer number').required('Stock is required').positive('Stock must be a positive number'),
    price: yup.number().nullable().required().moreThan(0),
    discount: yup.number().positive().lessThan(100),
    file: yup.mixed<File>().test('fileSize', 'The file is too large', (value) => {
        if(value instanceof File){
            return value && value.size <= 15*1024*1024;
        }else if(value === undefined || value === null){
            return true;
        }
        return false;
    })
    .test('fileType', 'Unsupported File Format', (value) => {
        if(value instanceof File){
            return value && ['image/jpeg', 'image/png', 'image/jpg'].includes(value.type);
        }else if(value === undefined || value === null){
            return true;
        }
        return false;
    })
});

创建产品时,始终需要文件(产品的图像),但在更新产品时则不需要。我尝试了多种声明表单钩子的方法,但我总是收到文件字段的错误,因为它是在两个接口中声明的,并且它们具有不同的类型( & )。FileFile | undefined

现在,我求助于两个 react 功能组件,它们为表单重复相同的代码,一个使用 create 模式和值,另一个使用 update 模式和值。

我如何使用表单值和架构的示例:

interface ProductFormProps {
    isLoading: boolean
    isOpen: boolean
    setIsOpen: (x: boolean) => void
    onSubmit: (x: CreateProductFormValues) => Promise<void>
}

export const CreateProductDialog: React.FC<ProductFormProps> = ({ isLoading, isOpen, setIsOpen, onSubmit }) => {
    const { handleSubmit, reset, control, watch, formState, formState: { errors } } = useForm<CreateProductFormValues>({
        resolver: yupResolver(CreateProductSchema)
    });...
reactjs typescript react-hooks 是的

评论


答: 暂无答案