Reputation: 217
Hello guys I'm trying to update the state of a nested object in react, I'm currently doing this:
handleChange({target: {id, value}}, type) {
this.setState(
state => ({
dwelling: (Object.assign(state.dwelling, {[id]: {[type]: value}}))
})
);
}
it comes from a formgroup:
<FormGroup controlId="spaces">
<ControlLabel>Dormitorios</ControlLabel>
<FormControl
componentClass="select"
value={dwelling.spaces.dorms}
placeholder="Seleccione"
onChange={e => this.handleChange(e, 'dorms')}
>
The problem is when I update the state of the sub object dwelling.spaces.dorms
is created but when I try to place another property it replaces the old one instead of getting added:
Before Dwelling
:
{
address: "",
currency: "",
price: 0,
publicationType: "",
spaces: {
closets: "",
dorms: "",
pools: ""
},
subtype: "",
type: ""
}
After onChange for dwelling.spaces.dorms
{
address: "",
currency: "",
price: 0,
publicationType: "",
spaces: {
dorms: "3",
},
subtype: "",
type: ""
}
After onChange for dwelling.spaces.closets
{
address: "",
currency: "",
price: 0,
publicationType: "",
spaces: {
closets: "3",
},
subtype: "",
type: ""
}
Upvotes: 1
Views: 4217
Reputation: 21
I keep my form state in a complex object and to simplify my code I use this helper function in my "handleChange" function referenced by TextField, Select, etc..
export function updateObject(obj, keys, value) {
let key = keys.shift();
if (keys.length > 0) {
let tmp = updateObject(obj[key], keys, value);
return {...obj, [key]: tmp};
} else {
return {...obj, [key]: value};
}
}
React-redux/Material-UI example
let [formState, changeFormState] = useState({});
function handleChange(event) {
changeFormState(updateObject(formState, event.target.name.split('.'),
event.target.value));
}
<TextField className={classes.textfield} name='foo.bar' value=
formstate.foo.bar || ''} onChange={handleChange} />
Upvotes: 2
Reputation: 4176
This example uses ES6 spread operator to keep your old properties which is the equivalent of Object.assign.
So what was happening is you're not keeping your nested value.
this.setState({
dwelling: {
...this.state.dwelling,
[id]: {
...this.state.dwelling[id],
[type]: value
}
}
});
In your example you overwrote your value with a new object. Notice the bolded text below.
dwelling: (Object.assign(state.dwelling, {[id]: {[type]: value}}))
In the bolded text it specifically set a new object into state.dwelling without keeping the old values. So what we did is that we used the ES6 spread operator to help merge your old values with the new value
{
...this.state.dwelling[id],
[type]: value
}
Upvotes: 4