在我的react with typescript项目中,我使用Formik组件和Yup验证模式来验证地址表单。目前,它对现有用户工作得很好,因为initialValues填充了有效数据。此外,它还可以在用户输入时进行验证。现在,问题是对于一个新用户,其中initialValues为空,或者只有一些字段为空。因为窗体在初始化时验证空字段。我需要它不验证字段时,表单是一个新的使用初始化,但保持相同的行为验证字段的用户类型在它,并再次提交。
这是我到目前为止如何实现它的一个片段:
这是验证模式组件:
return Yup.object().shape({
street: Yup.string()
.required(messages.required)
.test(
'is-empty-or-whitespace',
'This field can t be empty',
(value) => value?.trim() !== ''
),
city: Yup.string()
.required(messages.required)
.test(
'is-empty-or-whitespace',
'This field can t be empty',
(value) => value?.trim() !== ''
),
state: Yup.string()
.required(messages.required)
.test(
'is-empty-or-whitespace',
'This field can t be empty',
(value) => value?.trim() !== ''
),
zip: Yup.string()
.required(messages.required)
.test(
'is-empty-or-whitespace',
'This field can t be empty',
(value) => value?.trim() !== ''
)
this is how Formik is used in my parent component:
<Formik
initialValues={{
street: addressValues.street,
city: addressValues.city,
state: addressValues.state,
country: addressValues.country,
}}
enableReinitialize={true}
onSubmit={() => {
submitHandler();
}}
validationSchema={validationSchema}
valdateOnChange={true}
validateOnBlur={true}
validateOnMount={true}
>
{({ values, errors, handleChange, setFieldValue, setValues }) => (
<Form id="addressForm">
<Col className="someclass">
<Row">
<MyInputFormControl
name="street"
type="text"
value={values.street}
placeholder=""
required={true}
disabled={false}
onChange={handleChange}
isInvalid={!!errors.street}
error={errors.street}
autoFocus
/>
</Row>
<Row">
<MyInputFormControl
name="city"
type="text"
value={values.city}
placeholder=""
required={true}
disabled={false}
onChange={handleChange}
isInvalid={!!errors.city}
error={errors.city}
/>
</Row>
<Row">
<MyInputFormControl
name="state"
type="text"
value={values.state}
placeholder=""
required={true}
disabled={false}
onChange={handleChange}
isInvalid={!!errors.state}
error={errors.state}
/>
</Row>
<Row">
<MyInputFormControl
name="country"
type="text"
value={values.country}
placeholder=""
required={true}
disabled={false}
onChange={handleChange}
isInvalid={!!errors.country}
error={errors.country}
/>
</Row>
</Form>
)}
</Formik>
到目前为止,我尝试设置validateOnMount={!isNewUser},将isNewUser传递给validationSchema,并像这样更改验证模式中的测试:
street: Yup.string()
.required(messages.required)
.test(
'is-empty-or-whitespace',
'This field can t be empty',
(value) => {
if (isNewUser) { return true; }
return value?.trim() !== '';
),
但这根本不起作用。
有没有一种方法可以使用Formik和Yup来实现我想要的结果?
2条答案
按热度按时间nx7onnlm1#
在Formik中,有一个
touched
的概念。这个想法是,你可以只显示错误,当有一个验证错误和字段被 * 触摸 *(意味着用户已经与字段进行了任何有意义的交互)。基本上,在你的代码中,你可以沿着这些行做一些事情:
根据您使用的输入组件库,有时您需要手动将字段标记为 touched,但在您的情况下,这似乎是不必要的,因为您使用的是来自Formik的
handleChange
。也许还值得添加onBlur={handleBlur}
。eni9jsuy2#
您遇到的问题是由Formik组件的validateOnMount prop 引起的。当validateOnMount设置为true时,Formik会在表单初始化后立即对其进行验证。
在给定的用例中,您不希望表单验证最初为新用户触发,因此应该将validateOnMount设置为false。这应该可以解决问题。表单验证仍然会在用户输入和提交时触发,因为您已经将validateOnChange和validateOnBlur设置为true。
下面是代码的修改部分:
此更改确保表单在挂载时(即,当表单首次呈现时)不会进行验证,但在用户与表单交互时仍会进行验证。如果addressValues对象被更新(比如,当一个新用户登录时),表单将使用新值重新初始化,这要归功于enableReinitialize={true} prop,但它不会立即验证,因为validateOnMount是false。