Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't the Formik `touched` property being populated?

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} />
                &nbsp; Submit
              </Button>
            </Form.Row>
          </Form>
        );
      }}
    />
  );
}

What am I doing wrong here? The console.log(touched) always shows an empty object.

like image 328
djheru Avatar asked Aug 07 '19 01:08

djheru


People also ask

How does Formik touch work?

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 .

Why does Formik touch all fields before submit?

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.

What is dirty Formik?

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.

How do I access values in Formik?

it is very simple just do console. log(formik. values) and you will get all the values without submitting it.


2 Answers

@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.

like image 93
Bartek Fryzowicz Avatar answered Sep 20 '22 16:09

Bartek Fryzowicz


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>
like image 20
djheru Avatar answered Sep 19 '22 16:09

djheru