我正在使用 React、Formik、react-bootstrap 和 yup 制作一个表单进行验证。我正在尝试显示验证错误,但
touched
属性未填充字段。
const schema = yup.object({
name: yup.string().required(),
email: yup
.string()
.email()
.required(),
});
const ChildForm = props => {
const { child: { name = '', email = '' } = {} } = props;
const submitHandler = ({name, email}) => console.log(name, email);
return (
<Formik
validationSchema={schema}
onSubmit={submitHandler}
initialValues={{ name, email }}
render={({ handleSubmit, handleChange, values, touched, errors }) =>
{
console.log('touched: ', touched);
return (
<Form noValidate className="mt-4" onSubmit={handleSubmit}>
<Form.Row>
<Form.Group as={Col} controlId="name">
<Form.Label>Full Name</Form.Label>
<Form.Control
name="name"
required
value={values.name}
onChange={handleChange}
isValid={touched.name && !errors.name}
isInvalid={touched.name && errors.name}
type="text"
placeholder="Your child's name"
/>
<Form.Control.Feedback>Looks good!</Form.Control.Feedback>
<Form.Control.Feedback type="invalid">
{errors.name || 'Please enter your child\'s name'}
</Form.Control.Feedback>
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col} controlId="email">
<Form.Label>Email Address</Form.Label>
<Form.Control
name="email"
required
value={values.email}
onChange={handleChange}
isValid={touched.email && !errors.email}
isInvalid={touched.email && errors.email}
type="text"
placeholder="Your child's email address"
/>
<Form.Control.Feedback>
No spam, we promise!
</Form.Control.Feedback>
<Form.Control.Feedback type="invalid">
{errors.email || 'Please enter a valid email address'}
</Form.Control.Feedback>
</Form.Group>
</Form.Row>
<Form.Row className="float-right">
<Button variant="success" onClick={handleSubmit}>
<Icon icon={faSave} />
Submit
</Button>
</Form.Row>
</Form>
);
}}
/>
);
}
我在这里做错了什么?
console.log(touched)
始终显示空对象。
@djheru 您的解决方案是正确的,因为 Formik 在
touched
事件而不是 blur
上设置 change
标志。 这里是 Formik 作者对此的评论:
您必须致电 Formiks handleBlur
来通知 Formik blur
事件已被触发 - 所以是的,需要这些处理程序。
我通过访问在
handleBlur
函数参数中传递的 render
函数并将其添加为每个表单元素的 onBlur
处理程序来使其工作。不确定是否需要这样做,因为我正在使用react-bootstrap表单组件,但react-bootstrap文档有一个Formik示例,但touched
对象没有得到更新。
(
<Formik
validationSchema={schema}
onSubmit={submitForm}
initialValues={{ name, email }}
render={({
handleSubmit,
handleChange,
handleBlur, // handler for onBlur event of form elements
values,
touched,
errors,
}) => {
return (
<Form noValidate className="mt-4" onSubmit={handleSubmit}>
<Form.Row>
<Form.Group as={Col} controlId="nameControl">
<Form.Label>Full Name</Form.Label>
<Form.Control
name="name"
required
value={values.name}
onChange={handleChange}
onBlur={handleBlur} // This apparently updates `touched`?
isValid={touched.name && !errors.name}
isInvalid={touched.name && errors.name}
type="text"
placeholder="Your child's name"
/>
<Form.Control.Feedback>Looks good!</Form.Control.Feedback>
<Form.Control.Feedback type="invalid">
{errors.name || 'Please enter your child\'s name'}
</Form.Control.Feedback>
</Form.Group>
</Form.Row>
我的案例是
number().optional()
领域。 Formik 在处理 undefined
值时遇到问题。
切换到
number().required().nullable()
和 null
对我来说很方便:
// ❌ BAD
<input
type="number"
value={someOptionalNumber}
onChange={({ target }) => setValue(target.valueAsNumber || undefined)}
/>
// ✅ GOOD
<input
type="number"
value={value ?? ""} // prevent "should not be null" error
onChange={({ target }) => setValue(target.valueAsNumber || null)}
/>