Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

validateOnMount triggers validation with initialValues when re-rendered #2046

Closed
TLadd opened this issue Nov 18, 2019 · 16 comments
Closed

validateOnMount triggers validation with initialValues when re-rendered #2046

TLadd opened this issue Nov 18, 2019 · 16 comments

Comments

@TLadd
Copy link

TLadd commented Nov 18, 2019

馃悰 Bug report

Current Behavior

Re-render causes validateOnMount to run again with initialValues, producing incorrect validation results.

Video of re-render triggering validation with initialValues

This may be intended behavior, but I found it pretty unexpected, especially since the name of the prop is validatesOnMount. The docs do mention that it runs when initialValues changes, so it is behaving as documented. It's a little not-so-obvious though.

Expected behavior

validateOnMount should only run when the component initially mounts.

Reproducible example

https://codesandbox.io/s/formik-example-no1kc

Suggested solution(s)

Remove initialValues from the dependencies array for the validateOnMount useEffect.

If the current behavior is desired, perhaps add a more explicit warning about the need to memoize initialValues when using validateOnMount.

Additional context

Your environment

Software Version(s)
Formik 2.0.4
React 16.12.0
TypeScript 3.7.2
Browser Chrome
npm/Yarn Yarn
Operating System OS X
@andreoav
Copy link

I have a similar problem, validateOnMount is causing a render loop.

@sibelius
Copy link

the problem is this

}, [props.initialValues, validateOnMount, validateFormWithLowPriority]);

you need to useMemo your initialValues

but even using this, it is causing rerender

@georgefeast
Copy link

This only seems to be a problem from version 2.0.4 onwards. Has anyone else found this?

@sgronblo
Copy link
Contributor

I've been tearing my hair out over this today before finally figuring out what was going on. I also feel it's quite unintuitive that initialValues is used as a dependency for the initial validation useEffect.

I ended up working around it by not creating the initialValues object inside the render function, but instead creating it one level up and passing it down into my component that is using Formik.

@desfero
Copy link

desfero commented Dec 23, 2019

I believe the behavior here should be the same as with enableReinitialize which uses deep object comparison under the hood.

@arianitu
Copy link

I am running into this as well. My initialValues are being used instead of the actual Formik field values for validation leading to the form being invalid when it is really valid.

Anyone found a solution?

@andycarrell
Copy link

Hi @arianitu we've created a work around which is to "freeze" initial values so that they never change, thus never trigger this validation effect:

function useFreeze(initializer) {
    const [frozenValue] = useState(initializer);
    return frozenValue;
}

// wherever formik is used: (Not able to be used with `withFormik`)
  const {
    errors,
    touched,
    values,
  } = useFormik({
    initialValues: useFreeze({
      question: defaultValues.question || "",
      answer: defaultValues.answer || "",
    }),
    ...
  });

@arianitu
Copy link

Thank you for your solution @andycarrell , but I don't really want to do that everywhere, this bug is awful, we may downgrade to 1.x.

@jaredpalmer this seems like a pretty bad bug in 2.x, shouldn't initialValues just set the values of Formik and then validation should only act on the actual values?

All our forms are affected since we want Save buttons etc to be disabled before a user can interact with them. With this bug, it breaks all our forms because we sometimes pass values of inputs up the chain and cause re-renders.

@arianitu
Copy link

@andycarrell considering this is from November, I don't think it's going to get fixed soon, so I guess I'll use your solution. This also works:

  let initialValues = useMemo(() => {
    return {
      name: '',
      size: ''
    }
  }, []);

@luansantosti
Copy link

Yep @arianitu this works fine for me.

@TLadd
Copy link
Author

TLadd commented Feb 7, 2020

Haven't tested it yet, but this looks to me like it would fix the bug: #2243

@TLadd TLadd closed this as completed Feb 7, 2020
@omatei-brightplan
Copy link

This issue came back again after 2.1.6

@andrewphamvk
Copy link

I am experiencing this issue on 2.2.9.

useMemo works but hope this gets fixed..

@egemon
Copy link

egemon commented Jul 6, 2021

+1

@johnrom
Copy link
Collaborator

johnrom commented Jul 6, 2021

This should be fixed in my v3 alpha: #3231

The specific code that fixes it is here, and can be applied to v2 as well:

https://github.com/formium/formik/pull/3231/files#diff-2421f0a25f33b0ee81ca1de9dee2a1743711e08f273a5733ed03493de527de21R390-R402

https://github.com/formium/formik/blob/f24e1510ac07ad5821e23fd7a6048299dd630c86/packages/formik/src/Formik.tsx#L390-L402

I think there is still some room for improvement but I think the above is suitable for non-concurrent environments.

@Jakemangan
Copy link

Can confirm this is still an issue in the latest version.

My initial values is causing my whole form to validate + re-render on mount, despite validateOnMount being set to false.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests