Formik: Odd behavior of touched

Created on 25 Apr 2018  路  5Comments  路  Source: formium/formik

If I set up a form like this

class FormTest extends React.Component {

    state = {
        foo: {
            num: -1
        }
    };

    render()
    {
        return (
            <div>
                <Formik
                    initialValues={this.state.foo}
                    onSubmit={(values, actions) => {

                        console.log("Submitted: ", JSON.stringify(values));
                        actions.setSubmitting(false);
                    }}

                    render={({errors, touched, isSubmitting, isValid}) => (
                        <Form>
                            <Field type="text" name="num" validate={v => isNaN(+v) ? "Invalid Number" : null}/>
                            {errors.num && touched.num && <div>{errors.num}</div>}
                            <button type="submit" disabled={ isSubmitting }>
                                Submit
                            </button>
                        </Form>
                    )}
                /></div>
        )
    }
}

Current Behavior

I can observe the very odd behavior related to the "touched" status of the num field.

I load the component, change the input to "-1a". No errors is displayed, because the field is not "touched" yet. If I blur once, it counts as touched and shows the expected behavior: Toggling from "Invalid Number" according to the validity of the input.

Even more odd: If I submit the form once first, the field is flagged as touched instantly, and the first edit changes the error display

Desired Behavior

Changing a field value is clearly "touching" the field, especially if just focusing and bluring it is "touching". While I understand the current behavior it seems neither expected nor really desirable.

Suggested Solutions

Flag changed fields as "touched".

Additional Information

Full Example: https://github.com/fforw/curly-octo-funicular

  • Formik Version: 0.11.11
  • React Version: 16.3.2
  • TypeScript Version: ---
  • CodeSandbox Link: ---
  • OS: Linux
  • Node Version: v8.11.1
  • Package Manager and Version: yarn 1.6.0
stale

Most helpful comment

IMO there's no need for a fix or new props:

load the component, change the input to "-1a". No errors is displayed, because the field is not "touched" yet. If I blur once, it counts as touched and shows the expected behavior: Toggling from "Invalid Number" according to the validity of the input.

If you want to see validation errors as they happen during input, wouldn't you just write

{errors.num && <div>{errors.num}</div>}

instead of

{errors.num && touched.num && <div>{errors.num}</div>}

I'm wondering if there's any use for touched at all, besides visually indicating a field to the user as "being visited"?

Even more odd: If I submit the form once first, the field is flagged as touched instantly, and the first edit changes the error display

By clicking on the submit button, the input loses focus, which triggers the blur event. The blur event causes the Field component to set the field as touched.

All 5 comments

My expectations for behavior are similar to @fforw's. My current workaround:

<Formik
   render={({handleChange, setFieldTouched, ...props}) => {
      ...
      return (
         ...
         <input
            onChange={(...args) => {
               setFieldTouched('myField');
               handleChange(...args);
            }}
            {...otherStuff}
         />
      ...
   }}
/>

However, I really do think setting touched#myField to true whenever a change event occurs _should_ be the default behavior.

From #737 PR thread comment:

touched fires onBlur. Current behavior is intentional.

@jaredpalmer: I think what @fforw and myself are challenging here is that design intent to flip touched _only_ on blur and _not_ change.

1) Would you consider an additional Formik prop (e.g.; touchOnChange)?

2) I hesitate to maintain a competing impl of Field in my project. Is the workaround above advisable?

This issue can probably be closed.

IMO there's no need for a fix or new props:

load the component, change the input to "-1a". No errors is displayed, because the field is not "touched" yet. If I blur once, it counts as touched and shows the expected behavior: Toggling from "Invalid Number" according to the validity of the input.

If you want to see validation errors as they happen during input, wouldn't you just write

{errors.num && <div>{errors.num}</div>}

instead of

{errors.num && touched.num && <div>{errors.num}</div>}

I'm wondering if there's any use for touched at all, besides visually indicating a field to the user as "being visited"?

Even more odd: If I submit the form once first, the field is flagged as touched instantly, and the first edit changes the error display

By clicking on the submit button, the input loses focus, which triggers the blur event. The blur event causes the Field component to set the field as touched.

Hola! So here's the deal, between open source and my day job and life and what not, I have a lot to manage, so I use a GitHub bot to automate a few things here and there. This particular GitHub bot is going to mark this as stale because it has not had recent activity for a while. It will be closed if no further activity occurs in a few days. Do not take this personally--seriously--this is a completely automated action. If this is a mistake, just make a comment, DM me, send a carrier pidgeon, or a smoke signal.

ProBot automatically closed this due to inactivity. Holler if this is a mistake, and we'll re-open it.

Was this page helpful?
0 / 5 - 0 ratings