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.
Like errors and values , Formik keeps track of which fields have been visited. It stores this information in an object called touched that also mirrors the shape of values / initialValues . The keys of touched are the field names, and the values of touched are booleans true / false .
On submit, Formik should set all fields as touched and therefore display the error messages for any field that has an error, regardless if they have been touched by the user or not. The author mentions here that all fields are set to touched before submit.
Returns true if values are not deeply equal from initial values, false otherwise. dirty is a readonly computed property and should not be mutated directly.
it is very simple just do console. log(formik. values) and you will get all the values without submitting it.
@djheru Your solution is correct because Formik sets touched
flags on blur
event instead of on change
. Here is Formik author comment about this:
You have to call Formiks handleBlur
to notify Formik that blur
event has been triggered - so yes, these handlers are needed.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With