I'm making a form with React, Formik, react-bootstrap, and yup for validation. I am trying to display validation errors, but the touched
property is not being populated with the fields.
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>
);
}}
/>
);
}
What am I doing wrong here? The console.log(touched)
always shows an empty object.
I got it working by accessing the handleBlur
function that's passed in the render
function argument, and adding that as an onBlur
handler for each of the form elements. Not sure if that's needed because I'm using react-bootstrap form components, but the react-bootstrap docs have a Formik example, but the touched
object was not getting updated.
(
<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>