Reputation: 59
I'm buidling a react form with reusable components.
I'd like to update my json so I can nest some data, but I'm getting a "controlled vs uncontrolled" error (again!) which I can't solve. I've been researching on it, but I'm probably lacking the right vocabulary to be efficient. Where or how should I define "pet"..?
Later, my goal is to be able to add several pets to one owner.
PetsForm
import React, { useState, useEffect } from 'react';
import Controls from './reusables/Controls';
import { useForm, Form } from './reusables/useForm';
const initialFieldValues = {
id: 0,
owner: '',
pet : [{
petName: '',
petBreed: ''
}]
}
export default function PetsForm(props) {
const {
values,
setValues,
errors,
setErrors,
handleInputChange,
resetForm
} = useForm(initialFieldValues, true, validate);
return (
<Paper>
<Box>
<Controls.Input
label="Owner"
name='owner'
placeholder="Owner"
value={values.owner = values.owner.toUpperCase()}
onChange={handleInputChange}
/>
<Controls.Input
label="PetName"
name='petName'
placeholder="Pet Name"
value={values.petName = values.petName.toUpperCase()}
onChange={handleInputChange}
/>
<Controls.Input
label="PetBreed"
name='petBreed'
placeholder="Pet Breed"
value={values.petBreed}
onChange={handleInputChange}
/>
</Box>
</Paper>
etc...
}
My useForm
export function useForm(initialFieldValues, validateOnChange=false, validate) {
const [values, setValues] = useState(initialFieldValues);
const [errors, setErrors] = useState({});
const handleInputChange = event => {
const { name, value } = event.target
setValues({
...values,
[name]: value,
})
if(validateOnChange)
validate({
[name]: value,
})
}
return {
values,
setValues,
errors,
setErrors,
handleInputChange,
};
}
Upvotes: 0
Views: 1120
Reputation: 5497
You are getting the error because your values values.petName
and values.petBreed
is undefined
. Because your shape of values is
const initialFieldValues = {
id: 0,
owner: '',
pet : [{
petName: '',
petBreed: ''
}]
}
So the petname
and petBreed
has to refered as values.pet.[0].petName
and values.pet.[0].petBreed
.
Setting the value of nested Object
You can use the lodash set to set the value of deeply nested object . All you need to do is to provide the name
as dotted path values . For petname you need to provide the name
attribute as pet.[0].petName
Now we can set the values of your value object using lodash set,
const handleInputChange = event => {
const { name, value } = event.target
// clone the values . you can use lodash cloneDeep for this
set(clonedValues, name, value);
setValues(clonedValues);
....
}
Now you can retrieve the deeply nested values as
<Controls.Input
label="PetBreed"
name='pet.[0].petBreed'
placeholder="Pet Breed"
value={values.pet.[0].petBreed}
onChange={handleInputChange}
/>
Upvotes: 1