When a fields value is an object instead of an array / string, a change to the value will not dirty the form. This causes the form to require another item to be changed for the form to dirty, and in the case where isInitialValid is false, for the form to even be valid.
Click the "Add my address" button
A new property should be added to testObj ( new value of myAddress: 222 Place)
The new property should be displayed below "Addresses"
The form should be dirtied and become valid. The submit button should be clickable.
Clicked the "Add my address" button
A new property is added to testObj ( new value of myAddress: 222 Place)
The new property is displayed below "Addresses"
The form IS NOT dirtied and remains invalid. The submit button is not clickable.
https://codesandbox.io/s/w6z5r0nmp8
The contrived example is the user is on a form and clicks a button to add their address to the form.
I left in the e-mail section so that you can see how the form should dirty / become valid.
The issue appears to be that when copying values to initial values (and back on reset), it is not being deep copied so the object is a reference copy. This means when the value is changed, the saved initial value is changed, making it look like the form still isn't dirty when the initial values are compared to the current values to check if it is dirty.
I think the problem is manifesting on Formik.tsx:560, where the dirty value is calculated. I was able to get it working as expected by adding a cloneDeep whenever value was set to initialValue or initialValue was set to value.
| Software | Version(s) |
| ---------------- | ---------- |
| Formik | 1.3.1 |
| React | 16.5.2 |
| TypeScript | 3.1.3 |
| Browser | Chrome 70.0.3538.110 |
| npm/Yarn | npm 6.4.1 |
| Operating System | MacOS 10.14.1 |
it seems using setFieldValue works just fine.
https://codesandbox.io/embed/625q5w7l0w
Had the same problem, and was using setFieldValue.
The gotcha is using the same reference to the values object :
not working
// directly updating the `values` object :
values.testObj.myAddress = "222 Place";
setFieldValue("testObj", values);
working
const newValues = {...values, myAddress: "222 Place"};
// or
const newValues = Object.assign({}, values); // clone values
newValues.myAddress = "222 Place";
setFieldValue("testObj", newValues);
This is not a bug as you setXXXX work like setState and must be immutable
Most helpful comment
This is not a bug as you setXXXX work like setState and must be immutable