Formik: Field validator submits validation result after field is unmounted and unregistered

Created on 24 Mar 2020  ·  10Comments  ·  Source: formium/formik

🐛 Bug report

First of all: Thanks a lot for formik and for your continued effort to provide a high quality open source library and support!

Current Behavior

I am creating a kinda "polymorphic" form (say it's namespace is "something") which allows toggling its type using a select and rendering other fields (called subfields) conditionally based on the selected type, e.g. there is a type A with field "something.foo" and type B with field "something.bar". When changing the type, values for the subfields are reset by setting a value for the complete "something" key.

Subfields have validate functions attached to them. When changing the type e.g. from type B to type A, the validator of field "bar" is run before field "bar" is unmounted, leaving over a validation error for "something.bar".

From debugging this, I could see that the execution order of the different lifecycles is like this:

  1. Setting new type
  2. Old field running validation (with low priority)
  3. Old field unmounting: unregistering field (with high priority)
  4. Field validation from 2. submitting results

Maybe I am doing something wrong? The code sandbox example is a simplified version of what I am doing. Interestingly, it works with formik 1.x. Any help, especially if it shows that it's just me being dumb is highly appreciated!

Expected behavior

It should be able to unregister a field before unmounting it and prevent further validations to run afterwards.

Reproducible example

I created a sandbox here. To see the issue, do the following:

  1. Change type to "B"
  2. See in Formik stats at the bottom that errors contains an entry for foo, although no foo field exists anymore.

Suggested solution(s)

Additional context

Your environment

| Software | Version(s) |
| ---------------- | ---------- |
| Formik | 2.1.4
| React | 16.13.1
| TypeScript |
| Browser |
| npm/Yarn |
| Operating System |

Most helpful comment

I faced the same issue. Form validation on that field runs after the field was unmounted even when trying reset errors on field unmount.

All 10 comments

I faced the same issue. Form validation on that field runs after the field was unmounted even when trying reset errors on field unmount.

Hey @jaredpalmer, do you have any advice for us? Maybe we are doing something wrong. Is it even supposed to work with fields mounting/unmounting & registering/unregistering having custom validation functions attached to them?

@dennisoelkers I've fixed my issue with, probably, some workaround. In my case, I just need to drop unmounted field value from formik state and don't fire validation on an unmounted field ( this is the sense of issue).

I've combined two approaches to accomplish it. I'm not sure about the unregistering field, instead, I've used formik.setFieldValue() with disabled validation on field unmount with a conjunction of Yarn conditional validation (https://github.com/jquense/yup#mixedwhenkeys-string--arraystring-builder-object--value-schema-schema-schema).

I tried to do the same with field validation function, but it doesn't fire on the unmounted fields.

Therefore, when the field gets unmounted, yarn conditional validation checks my trigger field value and just doesn't run validation on it.

Hope that would help you.

Hey @rusyurchenko!

Thanks for the update. How do you use setFieldValue with disabled validation on field unmount? Do you have a code snippet for me by any chance?

@dennisoelkers I have my own custom inputs, therefore, I have full control over it. SImple call setFieldValue on useEffect clear function.

  const formik = useFormikContext();
  useEffect(
    () => () => {
      formik.setFieldValue(name, undefined, false);
    },
    []
  );

Thanks, @rusyurchenko!

That does not really solve it for me. When setFieldValue is called, the field validator has already been kicked off. The main issue is that the validator's result is submitted _after_ anything triggered explicitly during unmounting.

That's why I've used a Yup conditional validation. It didn't fire validation after the field was unmounted. As I said previously it’s just a workaround OR desired behavior by design.

I am maybe a bit slow here, but how is yarn related? I think you mean yup? I have not used yup before, I think it does mean though that a validation schema is defined on the parent Formik component, which knows about the fields? I am using field level validation because the parent component does not know about the structure of the child components rendering Fields.

How does your yup schema look like, that fixes validation running after unmounting the field?

any updates?

Wow, curious that more people faced the same problem! So +1 on this.

I am building a stepper and need to conditionally add field to formik state or or remove them because if not after user passes a stepper form values includes a lot of trash field values that are left from branches.

So when inside of a from a different branch is selected, and another set of fields is rendered instead of previous set of fields, the cleanup of old fields in formik state is required.

Tested out internal form.registerField and form.unregisterField methods but they are not giving me anything yet.

UPDATE: found that method form.setValues allows you to set entirely new form data shape.

const prevFormValues = {
    name: 'Walter',
    surname: 'White'
}

...
form.setValues({
    name: 'Jack'
})
...

// nextFormValues will be → { name: 'Jack' } 

Hope it helps someone.

Was this page helpful?
0 / 5 - 0 ratings