formik icon indicating copy to clipboard operation
formik copied to clipboard

call to setFieldValue and setFieldTouched at once

Open israelKusayev opened this issue 5 years ago • 7 comments

I have a custom component and I have to call setFieldValue to change the value in Formik state.
But the touched property to this field is not change.

I guess that I need to call setFieldTouched, am I understand it correctly? Is there any other way to set the touched value when I call to setFieldValue?

israelKusayev avatar Sep 20 '19 11:09 israelKusayev

@israelKusayev if you want to act as if the field value changed normally, you can call formik.handleChange(field.name)(value), and all the setFieldTouched, validations, and other events will be called.

johnrom avatar Sep 21 '19 18:09 johnrom

The touched is still undefined

israelKusayev avatar Sep 25 '19 15:09 israelKusayev

Now that I think about it, setFieldTouched is only called on blur and during a submission attempt. Touched in formik implies that if the field isn't valid, the user will want to know. It exists because showing the user an error message while they are halfway through typing a phone number wouldn't make much sense. The best way to achieve what you're looking for is to manually call setFieldTouched. Note that you can still use handleChange if you'd still like the normal sequence of change events to occur.

johnrom avatar Sep 25 '19 16:09 johnrom

Just got this working with this:

const value = getIn(formik.values, fieldName)
const touched = getIn(formik.touched, fieldName)
const initialValue = getIn( formik.initialValues, fieldName )

useEffect(() => {
    const isTouched = value === initialValue
    if(touched != isTouched) formik.setFieldTouched(name, isTouched)
},[ value ])

i think if the value change, it should automatically be marked as touched.

juji avatar Oct 27 '20 08:10 juji

I had this problem too and i fixed it by : await props.setFieldTouched("Discription", true) await props.setFieldTouched("Username", true)

                                        props.handleChange(Username)(" ")

setting all the values touched true and set one of the values space. I also change the required massage to be equal to min massage so that the user cant understand this.

setayeshk avatar Feb 01 '21 11:02 setayeshk

works for me... but I'm not sure if this solve is correct props.setFieldValue('name', 'John Doe').then(() => { props.setFieldTouched('name', true, true) })

other hand (I used this one):

(async () => {
    await props.setFieldValue('name', 'John Doe')
    await props.setFieldTouched('name', true, true)
})()

iqwik avatar Jun 14 '22 07:06 iqwik

works for me... but I'm not sure if this solve is correct props.setFieldValue('name', 'John Doe').then(() => { props.setFieldTouched('name', true, true) })

other hand (I used this one):

(async () => {
    await props.setFieldValue('name', 'John Doe')
    await props.setFieldTouched('name', true, true)
})()

The "await" for the setFieldValue may be redundant as it uses a separate dispatch. The promise is related to validation if I'm not mistaken.

I recommend removing the additional validation:

    (async () => {
       props.setFieldValue('name', 'John Doe', false) // <-- this line changed
        await props.setFieldTouched('name', true, true)
    })()

This is the code of the function in Formik repository:

  const setFieldValue = useEventCallback(
    (field: string, value: any, shouldValidate?: boolean) => {
      dispatch({
        type: 'SET_FIELD_VALUE',
        payload: {
          field,
          value,
        },
      }); // <-- value changes in dispatch
      const willValidate =
        shouldValidate === undefined ? validateOnChange : shouldValidate;
      return willValidate
        ? validateFormWithHighPriority(setIn(state.values, field, value))  // <-- validation only promise (not related to value update)
        : Promise.resolve();
    }
  );

WDT @iqwik ?

noyoliel-devocean avatar Mar 06 '24 22:03 noyoliel-devocean