In my case, I'm using React.js and I would like to dynamically update the values in the deployOptions
object.
For example -
initial state looks like:
getInitialState() {
return {
deployOptions: {
config: null,
action: 'deploy',
env: 'qa'
}
}
}
Obviously this is not correct - but this is what I'm trying to achieve
configOptionChange(option) {
// option -> { key: 'env', value: 'prod' }
this.setState({
[deployOptions.option.key]: option.value
});
}
so that my state would then be
{
deployOptions: {
config: null,
action: 'deploy',
env: 'prod' // only this changes
}
}
In my case, I'm using React.js and I would like to dynamically update the values in the deployOptions
object.
For example -
initial state looks like:
getInitialState() {
return {
deployOptions: {
config: null,
action: 'deploy',
env: 'qa'
}
}
}
Obviously this is not correct - but this is what I'm trying to achieve
configOptionChange(option) {
// option -> { key: 'env', value: 'prod' }
this.setState({
[deployOptions.option.key]: option.value
});
}
so that my state would then be
{
deployOptions: {
config: null,
action: 'deploy',
env: 'prod' // only this changes
}
}
Share
Improve this question
edited Dec 3, 2015 at 17:31
Ben
asked Dec 3, 2015 at 17:05
BenBen
5,3619 gold badges38 silver badges45 bronze badges
5 Answers
Reset to default 14It's not especially pretty, but I think this is the best you can do with ES6:
configOptionChange({ key, value }) {
this.setState({
...this.state,
deployOptions: {
...this.state.deployOptions,
[key]: value
}
});
}
It's basically equivalent to your own Object.assign
solution but using the ES6 spread (...
) operator (and argument destructuring for good measure).
Here's a second option that isn't as clever but feels a little cleaner to me:
configOptionChange({ key, value }) {
const { deployOptions: prevDeployOptions } = this.state;
const deployOptions = { ...prevDeployOptions, [key]: value };
this.setState({ ...this.state, deployOptions });
}
Just like these are nested
objects, you can nest
ES6 Computed Property Name like this:
[yourNestedObject]: {...yourNestedObject, [nestedObjectProperty]: value}
Here is an example function that will update an object's properties and the properties of nested objects. Where prop
is the property to change, value
is the value to assign, and propObj
is the name of your nested
object. I used useState
hook for this.
const [obj, setObj] = useState({
prop1: '',
prop2: '',
nestedObj: {
prop1: '',
prop2: ''
}
});
const updateObj = (prop, value, propObj=false) => {
if (propObj) {
setObj({...obj, [propObj]: {...obj[propObj], [prop]: value}})
} else {
setObj({...obj, [prop]: value})
}
}
I think this might do the trick - but if anyone has a better solution?
configOptionChange(option) {
this.setState({
deployOptions: Object.assign({}, this.state.deployOptions, {[option.key]: option.val})
});
}
I'm using reduce to update the state of a component from a passed string of path properties:
handleChangeNested(event) {
const target = event.target; //an <input /> tag
let newState = { ...this.state };
let valuePath = target.name.split('.'); //the input's name is the the keys of the state object like 'group1.input1'
// Move down in the state object until we get to the 'bottom' property and change its value
// If the object does not have the properties we create them on the fly
valuePath.reduce((acc, key, index, path) => {
if (index === path.length - 1) {
acc[key] = target.value;
}
acc[key] = acc[key] || {};
return acc[key];
}, newState);
this.setState(newState);
}
The best solution I know would be to use "immutable" library.
configOptionChange(option) {
// option -> { key: 'env', value: 'prod' }
this.setState(state => setIn(state, ['deployOptions', option.key], option.value));
}