Open james-portelli-cko opened 3 years ago
@jaredpalmer don't suppose you could have a quick look as I'm really at a loss on how to solve this one.
In my mind, the solution is when an array has been touched but has no values, it should just be an empty array []
.
Thanks for getting back to me @johnrom
I suppose that would also work, because we would differentiate between an array property being 'undefined' (not touched) or an '[]' (touched) in the touched object to show the errors.
Is there any reason the FieldArray helpers do not affect the touched status by default?
I don't have any idea, unfortunately.
No worries @johnrom, any idea who could pitch in on this one?
@james-portelli-cko Probably way too late, but what helped me was using lodash.isEqual
to compare the previous value with the new value and only set the new value if there was a change. Because otherwise, since [] === []
is false
, you are basically replacing the array every time, and I think that's resetting other stateful values under the hood. So, something like this should help touched
persist:
// import { usePrevious } from 'react-use'
// this is assuming `files` is coming from props
const previousFiles = usePrevious(files) ?? []
// ...
// somewhere else within Formik render, probably in your `onChange`
if (!isEqual(files, previousFiles)) {
formProps.setFieldValue('files', files)
formProps.setFieldTouched('files', true, false)
}
Bug report
The ISSUE
Im running into an issue displaying validation errors for FieldArrays using Formik and Yup.
Ideally, to provide a good user experience we would want to show errors related to a field only when the field has been touched by the user, and while this is quite easy to accomplish with normal fields, Im struggling to mimic the behaviour for FieldArrays.
The reality is that for FieldArrays the ‘touched’ state doesn’t match up well with the way errors can be raised by YUP validations.
There are two issues:
Formik will only manage the 'touched' state of items within the array but not the array itself so if you had a validation on the min and max amount of items on the array and the user removed all the items there will be no touched state for the array, but there will be an error.
FieldArray helpers dont update the touched state of an array when either 'pushing' or 'removing' items from the array.
The below is an example which demonstrates the above two issues:
With the following schema we expect there to be at least 1 item within ‘someArray’ but no more than 5 items.
Imagine the following initial formik state, at this point we wouldn’t want to show the someArray error because nothing has been touched.
If I ‘push’ and item to someArray, then it will not longer be an error and I would expect the following state:
Unfortunately when using the FieldArray helpers the 'touched' state isnt updated, so the actual state we would get is:
If I 'remove' the item added now, then the error will return and I would expect the following state:
Unfortunately again the FieldArray helpers don't update the 'touched' state. As a result this error wont be shown to the user (provided im only showing the error is the field was touched)
Expected behavior
array: true
Reproducible example
https://codesandbox.io/s/upbeat-shamir-hmiwq?file=/src/Users.tsx
Your environment