使用(ES6)计算的属性名称更新嵌套对象

时间:2015-12-03 17:05:41

标签: javascript reactjs

就我而言,我正在使用React.js,我想动态更新deployOptions对象中的值。

例如 -

初始状态如下:

getInitialState() {
    return {
      deployOptions: {
        config: null,
        action: 'deploy',
        env: 'qa'
      }
    }
  }

显然这不正确 - 但这正是我想要实现的目标

configOptionChange(option) {

    // option -> { key: 'env', value: 'prod' }

    this.setState({
      [deployOptions.option.key]: option.value
    });
  }

这样我的状态就会

{
    deployOptions: {
      config: null,
      action: 'deploy',
      env: 'prod' // only this changes
    }
}

4 个答案:

答案 0 :(得分:9)

它不是特别漂亮,但我认为这是你用ES6做的最好的:

configOptionChange({ key, value }) {
  this.setState({
    ...this.state,
    deployOptions: {
      ...this.state.deployOptions,
      [key]: value
    }
  });
}

它基本上等同于您自己的Object.assign解决方案,但使用ES6传播(...)运算符(以及参数解构以获得良好衡量标准)。

这是第二个选择并不聪明,但对我来说感觉更清洁:

configOptionChange({ key, value }) {
  const { deployOptions: prevDeployOptions } = this.state;
  const deployOptions = { ...prevDeployOptions, [key]: value };
  this.setState({ ...this.state, deployOptions });
}

答案 1 :(得分:1)

我认为这可能会成功 - 但是如果有人有更好的解决方案吗?

configOptionChange(option) {

    this.setState({
      deployOptions: Object.assign({}, this.state.deployOptions, {[option.key]: option.val})
    });

  }

答案 2 :(得分:0)

我正在使用reduce从传递的路径属性字符串中更新组件的状态:

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);
}

答案 3 :(得分:0)

我知道的最佳解决方案是使用“不可变”库。

configOptionChange(option) {       
  // option -> { key: 'env', value: 'prod' }

  this.setState(state => setIn(state, ['deployOptions', option.key], option.value));
}