Formik Yup 验证 运行 在触摸字段之前
Formik Yup validation running before field is touched
我有一个包含字段 items
的表单,该字段存储具有属性 image
和 name
的对象数组。 image
属性 接受一个文件但是是可选的,name
字段是必需的。
出于某种原因,当我触摸名称字段时,图像字段验证开始并抛出错误“图像太大”,这可以从 formik 的错误对象中看出。我不明白为什么会这样。下面是组件的代码和代码框,您可以在此处查看 https://codesandbox.io/s/new-fog-xs2wb?file=/src/components/form.js
import React from 'react';
import { Formik, Field, FieldArray } from 'formik';
import * as Yup from 'yup';
function MyForm(props) {
const FILE_SIZE = 5 * 1024 * 1024;
const SUPPORTED_FORMATS = ["image/jpg", "image/jpeg", "image/gif", "image/png"];
const validationSchema = Yup.object().shape({
items: Yup.array().of(Yup.object().shape({
image: Yup.mixed()
.test("fileSize", "Image is too large", (value) => value && value.size <= FILE_SIZE)
.test(
"fileFormat",
"Unsupported Format - We only allow images.",
(value) => value && SUPPORTED_FORMATS.includes(value.type)
),
name: Yup.string().required('Required')
}))
});
const initialValues = { items: [{
image: undefined,
name: ''
}]}
return (
<div className="container">
<Formik enableReinitialize={true}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={async (values, { setSubmitting, resetForm }) => {
setSubmitting(true);
console.log(values);
setSubmitting(false);
}}>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
setFieldValue,
}) => (
<form className="mt-3" onSubmit={handleSubmit}>
<FieldArray name="items">
{({ push, remove }) => (
<React.Fragment>
{values.items && values.items.length && values.items.map((item, index) => (
<div key={index}>
{/* <Field name={`items[${index}].image`} /> */}
<div className="form-group">
<label htmlFor="name">Name</label>
<input name={`items[${index}].name`} className="form-control" id="name" aria-describedby="nameHelp" onChange={handleChange} onBlur={handleBlur} />
<small id="nameHelp" className="form-text text-muted">Enter a descriptive name for the item.</small>
</div>
<button type="button" className="btn btn-danger mr-2 mb-2" onClick={() => remove(index)}>Remove</button>
</div>
))}
<button type="button" className="btn btn-secondary mr-2 mt-4" onClick={() => push({image: undefined, name: ''})}>Add</button>
<button type="submit" disabled={isSubmitting} className="btn btn-primary mt-4">Submit</button>
<pre className="mt-2">{JSON.stringify(errors, null, 2)}</pre>
</React.Fragment>
)}
</FieldArray>
</form>
)}
</Formik>
</div>)
}
export default MyForm;
如何让它按预期工作?
非常感谢您的帮助。
Formik
提供了许多用于验证的实用程序,您可以使用以下组合来达到您的目的:
validateOnChange={false}
validateOnBlur={true}
这将解决您的问题,如果无论如何都不起作用,请删除 validateOnBlur
您在测试方法中使用的函数 应该 return false 以显示 resp 错误消息 。参考:https://github.com/jquense/yup#mixedtestoptions-object-schema
所以你应该这样做
!(value?.size > FILE_SIZE)
和
!(value && !SUPPORTED_FORMATS.includes(value.type))
使其发挥作用!
代码更新:
image: Yup.mixed()
.test(
"fileSize",
"Image is too large",
(value) => !(value?.size > FILE_SIZE)
)
.test(
"fileFormat",
"Unsupported Format - We only allow images.",
(value) => !(value && !SUPPORTED_FORMATS.includes(value.type))
),
我有一个包含字段 items
的表单,该字段存储具有属性 image
和 name
的对象数组。 image
属性 接受一个文件但是是可选的,name
字段是必需的。
出于某种原因,当我触摸名称字段时,图像字段验证开始并抛出错误“图像太大”,这可以从 formik 的错误对象中看出。我不明白为什么会这样。下面是组件的代码和代码框,您可以在此处查看 https://codesandbox.io/s/new-fog-xs2wb?file=/src/components/form.js
import React from 'react';
import { Formik, Field, FieldArray } from 'formik';
import * as Yup from 'yup';
function MyForm(props) {
const FILE_SIZE = 5 * 1024 * 1024;
const SUPPORTED_FORMATS = ["image/jpg", "image/jpeg", "image/gif", "image/png"];
const validationSchema = Yup.object().shape({
items: Yup.array().of(Yup.object().shape({
image: Yup.mixed()
.test("fileSize", "Image is too large", (value) => value && value.size <= FILE_SIZE)
.test(
"fileFormat",
"Unsupported Format - We only allow images.",
(value) => value && SUPPORTED_FORMATS.includes(value.type)
),
name: Yup.string().required('Required')
}))
});
const initialValues = { items: [{
image: undefined,
name: ''
}]}
return (
<div className="container">
<Formik enableReinitialize={true}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={async (values, { setSubmitting, resetForm }) => {
setSubmitting(true);
console.log(values);
setSubmitting(false);
}}>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
setFieldValue,
}) => (
<form className="mt-3" onSubmit={handleSubmit}>
<FieldArray name="items">
{({ push, remove }) => (
<React.Fragment>
{values.items && values.items.length && values.items.map((item, index) => (
<div key={index}>
{/* <Field name={`items[${index}].image`} /> */}
<div className="form-group">
<label htmlFor="name">Name</label>
<input name={`items[${index}].name`} className="form-control" id="name" aria-describedby="nameHelp" onChange={handleChange} onBlur={handleBlur} />
<small id="nameHelp" className="form-text text-muted">Enter a descriptive name for the item.</small>
</div>
<button type="button" className="btn btn-danger mr-2 mb-2" onClick={() => remove(index)}>Remove</button>
</div>
))}
<button type="button" className="btn btn-secondary mr-2 mt-4" onClick={() => push({image: undefined, name: ''})}>Add</button>
<button type="submit" disabled={isSubmitting} className="btn btn-primary mt-4">Submit</button>
<pre className="mt-2">{JSON.stringify(errors, null, 2)}</pre>
</React.Fragment>
)}
</FieldArray>
</form>
)}
</Formik>
</div>)
}
export default MyForm;
如何让它按预期工作? 非常感谢您的帮助。
Formik
提供了许多用于验证的实用程序,您可以使用以下组合来达到您的目的:
validateOnChange={false} validateOnBlur={true}
这将解决您的问题,如果无论如何都不起作用,请删除 validateOnBlur
您在测试方法中使用的函数 应该 return false 以显示 resp 错误消息 。参考:https://github.com/jquense/yup#mixedtestoptions-object-schema
所以你应该这样做
!(value?.size > FILE_SIZE)
和
!(value && !SUPPORTED_FORMATS.includes(value.type))
使其发挥作用!
代码更新:
image: Yup.mixed()
.test(
"fileSize",
"Image is too large",
(value) => !(value?.size > FILE_SIZE)
)
.test(
"fileFormat",
"Unsupported Format - We only allow images.",
(value) => !(value && !SUPPORTED_FORMATS.includes(value.type))
),