formik: setFieldError not working as expected.

🐛 Bug report

Current Behavior

Currently I want to validate a hostName URL using a function that I have and set errors accordingly.

here is the component on which I want to set the errors to -

<TextField
        name="github"
        value={values.github}
        onChange={event => handleLinkChange(event, 'github', 'github.com')}
        label="Please link your Github account"
        error={
          errors.github &&
          touched.github && {
            [errors.github]: true,
          }
        }
      />

and here is the handleLinkChange function that I use -

const handleLinkChange = ({ target: { value } }, name, hostName) => {
          setFieldValue(name, value);
          setFieldTouched(name, true);
          if (!isValidHostURL(hostName, value)) {
            console.log(name);
            setFieldError(name, `Enter a valid ${name} URL`);
          }
        };

the function is working fine as it should but the error is not being set accordingly.

Expected behavior

The error should be set and shown in the field

Reproducible example

Suggested solution(s)

Additional context

I am also using Yup for form validation schema and have set github to Yup.string().required() in the Yup.object().shape({}) along with the other fields

Your environment

Software Version(s)
Formik 1.4.2
React 16.6.3
TypeScript -
Browser chrome 69
npm/Yarn npm 6.4.1
Operating System Windows 10 1709

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 19 (1 by maintainers)

Most upvoted comments

setFieldError should not be used in change handlers because validation will not be aware of it during submission. The only real use case for setFieldError is inside of onSubmit where you want to manually set a field error. You should move this logic to validate instead.

@jaredpalmer what if on value change (or field blur) I want to immediately make an API call to check if value is valid and set error then, so that users can see errors and correct them before submitting form. A common use case is to check if username is available in signup forms.

set the third argument of setFeildValue to false: setFieldValue(name, value, false);

@nilamsavani @dagenius007 This works for me.

formik.setTouched({ username: true }, true);
formik.setErrors({ username: 'Enter a valid username' });

I had a use case where I solved it this way to remove any existing errors

formik.setFieldValue("password", generateValidPassword(), false);
formik.setFieldError("password", "");

In case my code helps someone formik v2.2.9

My custom input:

<InputDate
  label={birthdayInputLabel}
  errorMessage={formik.errors.birthday || ''}
  value={formik.values.birthday}
  onChange={formik.handleChange('birthday')}
  onStateChange={(state) => handleInputDateStateChange(state)}
/>

State handler:

const handleInputDateStateChange = async (state: string) => {
  await formik.setFieldTouched('birthday', true, true);
  formik.setFieldError(
    'birthday',
    state === 'error' ? 'ERROR_MESSAGE' : undefined,
  );
};

Any solution for this?