是的验证问题:存在各自值的字段仍然表示字段是必需的

问题描述

我正在使用 Yup 验证和 formik。我准备了初始值和validationSchema,并且在创建表单期间一切正常。但是在更新表单时,即使在各自的字段中预先填充了值,仍有一些字段显示“需要 abc 字段”。 (根据以下问题,名称和类型字段是必需的)

const initialValues = {
type: '',name: '',detail: {
    shareDetail: {
        tenantId: '',username: ''
    },blobDetail: {
        access: '',connection: ''
    }
}
}

const validationSchema = Yup.object().shape({
name: Yup.string().required(),type: Yup.string().required(),detail: Yup.object().required().when('type',{
    is: (selectedType) => selectedType === 'SHARE',then: Yup.object({
        shareDetail: Yup.object({
            tenantId: Yup.string().required(),username: Yup.string().required()
        })
    }),is: (selectedType) => selectedType === 'BLOB',then: Yup.object({
        blobDetail: Yup.object({
            access: Yup.string().required(),connection: Yup.string().required()
        })
    })
})
},['type'])

我的 jsx 是:

 <Formik initialValues={formData || initialValues} validationSchema={validationSchema} onSubmit={onSubmit} enableReinitialize validateOnMount>
            {formik => {
                return (
                    <Form>
                        <h5>Source</h5>
                        <div className='row'>
                            <div className='col-6'>
                                <FormControl control='select' label='Type *' placeholder='Enter Source Type' name='type' options={sourceTypes} AutoComplete
                                    value={getSourceTypeValue(formik.values.type)} onChange={e => handleSourceTypeSelect(e,formik.setFieldValue)} onBlur={() => handleSourceTypeBlur(formik.setFieldTouched)}
                                    outlineDanger={formik.errors.type && formik.touched.type ? 'mnd-danger' : ''} isdisabled={type !== 'createSourceButton'} />
                            </div>
                            <div className='col-12 mt-2'>
                                <FormControl control='input' type='text' label='Name *' placeholder='Enter Source Name' name='name'
                                    version={formik.touched.name && formik.errors.name ? 'mnd-danger' : ''} disabled={type !== 'createSourceButton'} />
                            </div>
                            <div className='col-12'>
                                <FormControl control='textarea' type='text' placeholder='Enter Source Description' label='Source Description' rows='3' name='description' />
                            </div>
                        </div>
                        <hr />
                        {formik.values.type === 'SHARE' && <>
                            <h5>Source Details</h5>
                            <div className="row mt-3">
                                {type === 'createSourceButton' && <div className="col-6 mt-2">
                                    <FormControl control='input' type='text' label='Tenant Id *' placeholder='Enter Tenant Id' name='detail.shareDetail.tenantId'
                                        version={formik.touched.detail && formik.errors.detail && formik.touched.detail.shareDetail.tenantId && formik.errors.detail.shareDetail.tenantId ? 'mnd-danger' : ''} />
                                </div>}
                                <div className="col-6">
                                    <FormControl control='input' type='text' label='Username *' placeholder='Enter Username' name='detail.shareDetail.username'
                                        version={formik.touched.detail && formik.errors.detail && formik.touched.detail.shareDetail.username && formik.errors.detail.shareDetail.username ? 'mnd-danger' : ''} />
                                </div>
                            </div>
                            <hr />
                        </>}
                        {formik.values.type === 'BLOB' && <>
                            <h5>Source Details</h5>
                            <div className="row mt-3">
                                <div className="col-12">
                                    <FormControl control='textarea' type='text' label='Connection String *' placeholder='Enter Connection String' rows='3' name='detail.blobDetail.connection'
                                        variant={formik.touched.detail && formik.errors.detail && formik.touched.detail.blobDetail.connectionString && formik.errors.detail.blobDetail.connectionString ? 'mnd-danger' : ''} />
                                </div>
                                <div className="col-12">
                                    <FormControl control='select' label='Access *' placeholder='Select Access' name='detail.blobDetail.access' options={accessOptions}
                                        value={getAccesstierValue(formik.values.detail.blobDetail.accesstier)} onChange={e => handleAccesstierSelect(e,formik.setFieldValue)} onBlur={() => handleAccesstierBlur(formik.setFieldTouched)}
                                        outlineDanger={formik.touched.detail && formik.errors.detail && formik.touched.detail.blobDetail.access && formik.errors.detail.blobDetail.access? 'mnd-danger' : ''} />
                                </div>
                            </div>
                            <hr />
                        </>}
                        <div className="btn-toolbar float-right" role="toolbar">
                            <div className="btn-group mr-2" role="group">
                                <Button variant='outline' onClick={() => handleCancel()}>Cancel</Button>
                            </div>
                            <div className="btn-group mr-2" role="group">
                                {type === 'createSourceButton' && <Button type='reset' onClick={() => resetForm()}>Reset</Button>}
                            </div>
                            <div className="btn-group" role="group">
                                <Button type='submit' disabled={!formik.isValid} onSubmit={() => onSubmit()}>
                                    {type === 'createSourceButton' ? 'Create' : 'Update'}
                                </Button>
                            </div>
                        </div>
                    </Form>
                )
            }}
        </Formik>

在源创建场景中一切正常,但更新按钮被禁用,如果我检查 formik 错误,它会说名称和类型是必填字段,即使它们各自的值在 UI 中正确填充。

解决方法

在定义初始值的过程中,您已经为 detail 属性的两种情况设置了所有道具,这会导致类型属性的每个值出现问题,这两个属性仍将存在于主对象上. 您可能想尝试以下操作:

const initialValues = {type: '',name: '',detail:{}};

const validationSchema = Yup.object().shape({
name: Yup.string().required(),type: Yup.string().required(),detail: Yup.object().when('type',{
    is: (selectedType) => !!selectedType && selectedType === 'SHARE',then: Yup.object.shape({
        shareDetail:Yup.object().shape({
            tenantId: Yup.string().required(),username: Yup.string().required()
        })
    }),is: (selectedType) => !!selectedType &&  selectedType === 'BLOB',then: Yup.object.shape({
        blobDetail: Yup.object().shape({
            access: Yup.string().required(),connection: Yup.string().required()
        })
    }),}).nullable().required() // you might also need this.
}); //,['type'])

,

问题可能出在您传递给 enableReinitializeformik 道具上。在文档状态中:

启用重新初始化?:布尔值

默认为假。控制是否Formik 如果 initialValues 更改(使用深度相等),则应重置表单。

https://formik.org/docs/api/formik#enablereinitialize-boolean

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...