Bug
When you have nested FieldArrays, let's say the following path: questions.0.values.0.label where questions and values are the arrays and label is a regular input field. When onBlur is invoked on label, it wants to touch the path. But at that point (due to changing the values array) the current touched state is:
questions: 0: {form_question_type_id: true, values: true}
which causes the following error in setDeep:
Uncaught TypeError: Cannot create property '0' on boolean 'true'
which happens on the last line of this method:
https://github.com/jaredpalmer/formik/blob/next/src/utils.ts#L69
It should update the touched state to a deep nested state like this:
questions: 0: {form_question_type_id: true, values: { label: true }}
I'm not sure I understand the current implementation of setDeep. Why not just clone the object and use something like https://github.com/kalmbach/bury?
To add onto this:
values.array is showing as an array, while touched.array is showing as an object. Both should have the same structure.
<FieldArray
name="products"
render={mutators => (
<div>
{values.products.map((product, index) => (
<Field name={`products.${index}`} key={index} label={`Product ${index + 1}`} component={Form.FormikProduct} />
))}
<Button type="button" size="mini" color="blue" onClick={() => mutators.push('')}>
Add
</Button>
</div>
)}
/>
This comes straight from props.values and props.touched
"values": {
"products": [
"",
""
]
},
"touched": {
"products": {
"0": true,
"1": true
}
}
Damn wish I knew about bury earlier. Will have to check this out more detail
why not stick with lodash and use set which works for bracket notation AND dot notation...
i believe this is a result of using dot notation to access array items.
i am using bracket notation, and the array field gets completely replaced with a boolean.
See https://github.com/jaredpalmer/formik/pull/362
awww, what was wrong with my PR? =X
Awww I'm sorry man. I was on a grind and just missed this. Agh.
@jaredpalmer Hi, thank you for new component ArrayField.
I noticed that torched and errors has a different data structure and after remove an item from values in touched property is not deleted. There is commit where was removed setFieldTouched.
"values": {
"email": "",
"firstName": "",
"lastName": "",
"emails": [
"test",
""
]
},
"errors": {
"firstName": "First name is required.",
"lastName": "Last name is required.",
"emails": [
null,
"emails[1] is a required field"
],
"email": "Email is required!"
},
"touched": {
"email": true,
"firstName": true,
"lastName": true,
"emails": {
"0": true,
"1": true,
"2": true
}
}
There are two elements in values and errors and three in touched. Fiddle
You will see that new item has an error due to touched.
-> changeValue -> setFieldValue -> runValidations in each of these methods, there is no logic which will update touched in the case when an item was removed
@jaredpalmer Is there any way to avoid this? Thanks in advance.
Working on a fix now.
I can't wait to merge my form branch into master!!
I figured it out! Will open a PR
@jaredpalmer I still get the error, when I leave the text box. Do I have to do something in code to dodge this error:
formik.es6.js:5556 Uncaught TypeError: Cannot create property '0' on boolean 'true'
Here is a code snippet:
<FieldArray
name="friends"
render={arrayHelpers => (
<Form>
<h3>Name</h3>
<input
name="name"
type="text"
value={values.name}
onChange={handleChange}
onBlur={handleBlur}
/>
{values.friends && values.friends.length > 0 ? (
values.friends.map((friend, index) => (
<div>
<MySelect
name={`friends.${index}.type`}
value={`friends.${index}.type`}
onChange={setFieldValue}
current={{ curVal: values.friends, index }}
options={[
{ value: "single_text", label: "Single Line Text" },
{ value: "multi_select", label: "Multi Select" }
]}
onBlur={setFieldTouched}
/>
{
values.friends[index] &&
<Field name={`friends.${index}.name`} />
It happens in the Field Component
@eferrervaughn any update? this issue is still occurring
It's good for me feel free to close
@eferrervaughn no, what i meant is that this is also happening in my code, did you solve it? :p
I'm also running into this error. Any updates? Should this issue be reopened?
Running into this as well on v1 and v2 and I'm noting using a FieldArray, just an array value. Thinking this unsolved @jaredpalmer
Not sure how to handle this situation tbh, maybe just encourage using resetForm in these cases rather than setFieldValue? The error that occurs is useless atm
For those looking for a solution I was doing something like:
// base on some condition I either
setFieldValue('text', '');
// or
setFieldValue('text', { default: '', keys: [] });
I was changing the shape of a field value which was causing the touched functionality to bork. After filling out text as a string and toggling it to the the object shaped formik's values and touched shape no longer match.
The solution is to use resetForm instead
resetForm(prevValues => ({ ...prevValues, text: '' });
// or
resetForm(prevValues => ({ ...prevValues, text: { default: '', keys: [] } });
@slightlytyler yes. Formik assumes that you keep you shape identical with respect to the path names. So in a nested situation if you go from a array to a value touched behavior could be off. you should indeed reset the form.
I don鈥檛 think this is a bug, but it is a contract that we should document more explicitly.
I was getting this error as well when using a custom slider input with setFieldValue and then typing and click out of a seperate empty Field or FastField component. Seems like the touched values were definitely off between array and value.
I fixed the issue and eliminated the error on my end by using a custom input component instead of Formik's Field or FastField components alongside my custom slider.
Old Input:
<FastField
name={`result[${index}].value[0]`}
className='form-control'
onChange={handleChange}
/>
New Input:
<input
name={`result[${index}].value[0]`}
className='form-control'
onChange={handleChange}
type='text'
value={values.result[index].value[0]}
/>
@elvisguillen So is your structure an array of array items? Trying to understand why you put value[0].
@jaredpalmer Is the documentation updated? Trying to find out how touched is being handled for an array of objects.
Most helpful comment
why not stick with lodash and use set which works for bracket notation AND dot notation...