formik: Formik does not re-render when initialValues change
Current Behavior
If there is an “external” component controlling initialValues
passed to Formik, Formik never updates it.
This may be desired behavior, however in my specific case I need to re-render the form (and ideally, warn the user about unsaved changes) with new initialValues
. If this is not a bug, any ideas on how to achieve this?
Steps to Reproduce
- Open https://codesandbox.io/s/kworjlq7n3
- Toggle between the select options
- You will see that all components in the chain re-render with new values, however Formik render never changes
initialValues
.
Expected behavior
When initialValues change, Formik should trigger a re-render and provide new initialValues in its render method.
CodeSandbox Link: https://codesandbox.io/s/kworjlq7n3
EDIT: CodeSandbox demonstrates a working solution
- Formik Version: 1.0.2
- React Version: 16.3.2
- TypeScript Version: N/A
- Browser and Version: Chrome Version 68.0.3440.84 (Official Build) (64-bit)
- OS: Mac OS 10.13.4
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 89
- Comments: 122 (4 by maintainers)
Aaaaaaaand… solved couple minutes after submitting this. The missing piece was
enableReinitialize
prop.Since this is open now, I’ll use the opportunity to ask if there is a way to
Thanks
working here
May I suggest to the authors of Formik that the default value of this defaults to true? It is counter-intuitive for it to behave this way without explicitly stating it
I just lost hours of coding because of this.
Doesn’t work for me …
does not work for me…
For me the presence of the
enableReinitialize
property doesn’t change anything. If the form hasn’t been touched (dirty
= false) the form is re-rendered if any property ininitialValues
is changed from outside ofFormik
. So far as expected. Once the form is changed by any user input (dirty
= true), changes to theinitialValues
triggers the render function but does not re-write thevalues
within the form. Thanks for any suggestions!enableReinitialize doesn’t work for me either.
Or you can set the element
key
like so:<Formik key={someId} ...
This tells react that this element has changed and should be re-rendered.
https://en.reactjs.org/docs/lists-and-keys.html#keys
enableReinitialize
still doesn’t work for me. The state changes but, innervalues
does not changes.My code:
There are few different issues people are talking about in this issue so it’s kind of hard to parse through the different threads. I’m going to try to help parse out the conversation as I understand it. I may get some things wrong.
initialValues
prop value and not seeing the form reset. This is by design and you have to setenableReinitialize
to make Formik re-initialize when a newinitialValues
prop value is set. https://github.com/jaredpalmer/formik/issues/811#issuecomment-410813925initializeValues
prop that is deeply equal to the previousinitializeValues
prop. They have also setenableReinitialize
totrue
, but still aren’t seeing Formik re-initialize. This is because Formik apparently doesn’t re-initialize if the newinitialValues
is deeply equal to the oldinitialValues
, even if they are different objects in memory. It sounds like the appropriate fix is to callresetForm
instead of trying to setinitialValues
or do some hack to make the objects not deeply equal. https://github.com/jaredpalmer/formik/issues/811#issuecomment-936601980initialValues
object and have setenableReinitialize
totrue
, but are noticing that on the next render of Formik descendants that Formik is providing the priorinitialValues
and not the newinitialValues
. If another render occurs later and Formik provides the newinitialValues
, it can result in a React warning likeWarning: A component is changing an uncontrolled input of type text to be controlled.
. This (to me) appears to be a bug in Formik and is solved by setting akey
value onFormik
that changes every time you set a newinitialValues
. https://github.com/jaredpalmer/formik/issues/811#issuecomment-505495937I am now giving the
Formik
component a key ofJSON.stringify(row)
to force formik to update when my filter and thus myrow
object changes. But that is a bit of a hack.Worked for me also, and I agree with @danieltodonnell , this is counter intuitive and I also spent hours searching the docs and the web to reach this thread as others have mentioned.
@linuxgg For god sake, you save my day
@robwold initially this is exactly how Formik worked. However, a lot of folks passing in data from redux wanted a way to turn this off. So we came up with
enableReinitialize
.you guys just need to follow the steps bellow:
Going to tackle better in docs.
It works for me by setting initialValues to empty string with useState
Then set enableReinitialize to true for Formik.
enableReinitialize={true}
Then use UseEffect to update the form when the screen loads.I encountered one error where enableReinitialize doesn’t do anything. The problem is that I wrapped around Formik to create customized Form component and I forgot to pass enableReinitialize to my customized form component… That took me an hour to figure out… Hope my experience could help if enableReinitialize doesn’t work for you.
@jaredpalmer took me hours to track this one down too. I’m new to both React and Formik, so there might well be a really good reason why this is the default behaviour. But part of the promise of Formik is that it’s “just React, and your Formik problems are really React problems”, and it seems to me that having your form not update with your state/props is a case where Formik really goes against the grain of React (and, arguably, the whole point of using React).
e.g. My use case was that when my page loads, I get the user’s existing data for them to edit from an API call in
componentDidMount
, which overwrote empty values set in the constructor. This is how tutorials tell you to do this sort of thing, so I’m sure that this pattern is pretty common? For details on how confused I got by this, see https://stackoverflow.com/questions/56246765/formik-values-not-updating-with-state/56252261#56252261@jaredpalmer it would be great if the documentation provided a rationale for the choice to set
enableReinitialize
to false. I’m having trouble pinpointing the use case for it beingfalse
. Is it because formik can’t tell how the properties are mapped to initial values? So an unrelated property could change, but the form’s values shouldn’t be reset because of it? But if that’s the case, isn’t this a design flaw in the protocol used between the parent component and the component that’s withFormik-wrapped? In other words, it’s something you’d want for the developer to fail during testing (if they change a property to a form that’s unrelated to its values?). I still feel I don’t quite get formik.For those who complain that the
enableReinitialize
is not working, make sure you are updating theinitialValues
using react local state. Consider these code:@jaredpalmer: Frist of all, Formik is absolutely great! Thanks so much! It does not really matter if the
enableReinitialize
setting is true/false but what is absolutely important that, 1.) enableReinitialize is mentioned in every example with a short note, including the Getting Started Guide. 2.) enableReinitialize has a better documentation. The Description is not obvious for a newbie. For a newbei sth. like “Tracking State” is much more obvious term. Resetting was the last I thought when I was looking for a solution. So many people report here having searched hours to solve the problem (including me). Please make this more ovious. Thanks so much.This thread saved me, thank you. Also agree that
enableReinitialize
should be enabled by default.@iamvanja Thanks so much for posting this issue and its solution. Seriously was driving myself nuts.
This last one saved my life. thanks.
I had problem with dirty form as @adammolnar mentioned so instead of reinitializing formik I have used form.resetForm(newValuesObject);
Docs: https://jaredpalmer.com/formik/docs/api/formik#resetform-nextvalues-values-void
When I use enableReinitialize along with reac-text-mask, the value is not changed. Has anyone had this problem before
Reinitializing is a destructive (and expensive) operation and will override any changes your users have made to your form. Just checking for reinitialization isn’t a free operation, depending on the size of your form states. Many people pass initial values like:
On every render, Formik would have to do a deep equals of those initialValues to make sure they are referentially equal. Since this is such a common pattern, Formik skips these checks by default and provides a simple opt-in to these checks,
enableReinitialize
.After opting in, you can get your initialValues from anywhere, but that anywhere has to trigger a render in React, which eventually comes down to Props or a Hook, whether a library-provided hook like Relay or Redux, or the result of a setState or dispatch when manually calling an API.
After reinitialise validations are not working…!!!
@godmar I figured it out … You have to set
value={field.value || ''}
in the input inside the TextInput component or whatever type you’re using in order to fix this issue.Making
enableReinitialize
true
by default would have been nice. Or, make it as a required prop if that is such a thing in react, so we are forced to put something in there, and will make appropriate decision accordingly. However, loving Formik, and appreciate your hard work.@jaredpalmer That was a fast response, thanks! I’m on 1.5.1. I appreciate that for Open Source you’ve got to balance the competing interests of different users, all of whom owe you something and not the other way round - just wanted to provide some feedback, especially as I’m not the only one who’s been caught out by this.
If anyone is still facing this issue even after setting
enableReinitialize
to true, Give formik a key that changes on every render likeDate.now()
, This is what worked for me.Thanks @Aaronius for a good explanation on different scenarios.
@giriss, yes, it is very common (though less frequent with hooks) for a developer to write the object inline:
If we did not do a deep comparison, Formik would reinitialize on every render in this scenario. This is more frowned upon with hooks since devs are generally expected to use state, but it’s still a fallback that I wouldn’t recommend removing.
If you are trying to reset the form with the same values, you can use
formik.resetForm()
.While editing the form, every time I change the value, the whole form re-renders and validation goes away for the fields which already appeared. Can anyone guide me please?
@rom5jp @saymow @DevMammadov codesandbox repro will help someone investigate your specific issue
@rom5jp @saymow I’d guess you need to translate the handleChange or handleBlur from your third party input library of choice to Formik’s api
@devmammadov I’d guess you need to memoize your API call / initialValues so that repeated API calls don’t cause the reinitialization
But there’s not much I can help with without a repro.
That has the same effect as making sure that all values are set in initialValues. The error occurs if a value is undefined, which you avoid with your
|| ''
fallback.after few hours of searching for answers and trying to fix this problem with re-render your “hack” is the only thing that worked! thanks!
Thanks for clarifying in such a nice way!
enableReinitialize is reseting all values to initial everytime i do a state change
when the enableReinitialize is set, and then the observer value changes, it resets the entire form and it only updates the field of the observer.
Is there a way to a preserve the form and I just update the observer field? TIA!
I think I know the answer to why the form does not reinitialize!! I guess Formik is comparing objects deeply!
For example
After the
useEffect
, the 2initialValues
are not equal (===
) ! But are deeply equal (if you compare them by attribute). The form does not reinitialize. Since formik does not detect any change in the twoinitialValues
. If you change it, example just adding a fake field, the form will reinitialize.Now it works!! It kinda sucks but maybe formik has a reason to deep compare the objects?
please help me, when I define enableReinitialize: true in formik, and defined initialValues then call api asyns to update the values of initialValues, it is not changed the value on the UI, please help me this. thanks so much.
This is helping even after years. Thanks.
For
enableReinitialize
to work for me, I had to use the render method. I couldn’t use the children property, in how you would typically pass children elements to within any other component: i.e.<Formik>{<my form elements />}</Formik>
doesn’t work but<Formik render={<my form elements />} />
worked… which is not at all intuitive and wasted me hours…Believe me, I am quite aware that it is a nuclear approach 😢 ! Unfortunately, although I have used Formik frequently enough in the past, I was unable to get the form reinitializing properly (values did not change). It is possible that my understanding of what gets initialized is flawed (maybe just internal state?), but the only way that I found to properly update the form values/state when parent props change was to “nuke” it by forcing a re-render. Thankfully this is only when the edit state changes, so it is not a large concern (since it re-renders then anyway, and a mount/unmount isn’t too worrisome there).
That is a “nuclear” approach as it unmounts and mounts the form component. Are you sure you are not doing something wrong?
I know this is an old thread, but I think enableReinitialize being false by default is a more sane choice. mostly forms are ephemeral, and you want the values to be set once, worked with, then sent out to a handler and be done.
Using
key
is a better approach. I’m dynamically updating the Form’s initial values andenableReinitialize
breaks the form state (e.g. touched fields).I’m facing this same issue when using <InputMask> component from react-input-mask. I’m looking for the solution for this scenario as well.
Adding
enableReinitialize
saved my bacon! => Thank you!This worked perfectly for me. Thank you
@johnrom Oh my god. I put attribute like html 😃 Sorry.
@multivoltage you have to pass
enableReinitialize={true}
to Formik.Thank-you so much.I had tried : enableReinitialize and bumping up the version, nothing worked except this last resort.Just gave a key with unique value to formik.Probably helps someone in need.Had spent a lot of time worrying I would have to give up on formik because of this.
I’m dynamically generating part of the form, and it always gives me the error …
Warning: A component is changing an uncontrolled input of type text to be controlled.
Setting enableReinitialize didn’t help. Here’s a StackOverflow post with the issue … https://stackoverflow.com/questions/58205963/formik-update-initial-values-after-api-callAnd here’s a link for sandbox … https://codesandbox.io/s/test-dynamic-inputs-with-formik-xr9qg
Any help would be appreciated.
This works with v1.5.1
Saved my life
I get the impression that enableReinitialize depends on some lifecycle happening.
Because at first, like many commenting above, I had a hard time getting my form to show any data at all. Then I added
enableReinitialize
and since then it updates, when initially loading the data from graphql.But I also have a situation (setting filters), when the form should update due to Mobx state changes.
The form dutifully re-renders every time the filter changes. But formik does not reinitialize its state.
How can I solve this?
@meetzaveri wrong version
Hummmm, OK, I see it is closed. Does that mean there is no way to check if the reinitialization happened?