Is it possible to store an object in the state of a React component? If yes, then how can we change the value of a key in that object using setState
? I think it
this.setState({abc: {xyz: 'new value'}});
will NOT work, as state.abc
will be entirely overwritten, not merged.
This works for me:
this.setState((previousState) => {
previousState.abc.xyz = 'blurg';
return previousState;
});
Unless I'm reading the docs wrong, Facebook recommends the above format. https://facebook.github.io/react/docs/component-api.html
Additionally, I guess the most direct way without mutating state is to directly copy by using the ES6 spread/rest operator:
const newState = { ...this.state.abc }; // deconstruct state.abc into a new object-- effectively making a copy
newState.xyz = 'blurg';
this.setState(newState);
this.setState({ abc.xyz: 'new value' });
syntax is not allowed.
You have to pass the whole object.
this.setState({abc: {xyz: 'new value'}});
If you have other variables in abc
var abc = this.state.abc;
abc.xyz = 'new value';
this.setState({abc: abc});
You can have ordinary variables, if they don't rely on this.props and this.state
.
You can use ES6 spread on previous values in the object to avoid overwrite
this.setState({
abc: {
...this.state.abc,
xyz: 'new value'
}
});
Easier way to do it in one line of code
this.setState({ object: { ...this.state.object, objectVarToChange: newData } })
Even though it can be done via immutability-helper or similar I do not wan't to add external dependencies to my code unless I really have to. When I need to do it I use Object.assign
. Code:
this.setState({ abc : Object.assign({}, this.state.abc , {xyz: 'new value'})})
Can be used on HTML Event Attributes as well, example:
onChange={e => this.setState({ abc : Object.assign({}, this.state.abc, {xyz : 'new value'})})}
In addition to kiran's post, there's the update helper (formerly a react addon). This can be installed with npm using npm install immutability-helper
import update from 'immutability-helper';
var abc = update(this.state.abc, {
xyz: {$set: 'foo'}
});
this.setState({abc: abc});
This creates a new object with the updated value, and other properties stay the same. This is more useful when you need to do things like push onto an array, and set some other value at the same time. Some people use it everywhere because it provides immutability.
If you do this, you can have the following to make up for the performance of
shouldComponentUpdate: function(nextProps, nextState){
return this.state.abc !== nextState.abc;
// and compare any props that might cause an update
}