Reactjs中如何使用动态键名进行setState()操作?

315

编辑:这是一个重复问题,请参见此处

我找不到在设置状态时使用动态键名的任何示例。这就是我想做的事情:

inputChangeHandler : function (event) {
    this.setState( { event.target.id  : event.target.value } );
},

在React中无法使用 event.target.id 作为状态键(key)进行更新吗?


4
这是与动态对象键相关的任何问题的重复。它不特定于React。 - Cory Danielson
11
var newstate = {}; newstate[event.target.id] = event.target.id; this.setState(newstate);翻译为: 创建一个名为"newstate"的变量; 在"newstate"中以事件触发器的id作为键和值,存储到"newstate"中; 使用"this.setState(newstate)"方法更新状态。 - Cory Danielson
谢谢,我对于一般对象的使用并不熟练。 - trad
@trad 我也遇到了这个问题,但是你在初始状态中放了什么呢?这不重要吧? - Raphael Onofre
14个回答

323

感谢 @Cory 的提示,我使用了这个:

inputChangeHandler : function (event) {
    var stateObject = function() {
      returnObj = {};
      returnObj[this.target.id] = this.target.value;
         return returnObj;
    }.bind(event)();

    this.setState( stateObject );    
},

如果你正在使用ES6或Babel转译器来转换你的JSX代码,你也可以使用计算属性名来完成这个操作:

inputChangeHandler : function (event) {
    this.setState({ [event.target.id]: event.target.value });
    // alternatively using template strings for strings
    // this.setState({ [`key${event.target.id}`]: event.target.value });
}

34
如果您使用bablejs构建代码,还有一种新的语法可以使用,即“计算属性名”。 - Cory Danielson
第二种方法会在Windows浏览器(IE,Chrome)中导致语法错误。有人注意到了吗? - benjaminz
谢谢 trad,这正是我寻找的,以避免在 <Radio /> 实现中出现代码重复。 - Adesh M
7
如果您使用计算属性名称来设置状态,例如 this.setState({ [event.target.id]: event.target.value });,那么如何使用 this.state...... 访问该状态呢? - user3574492
谢谢,这也帮助了我。 - Charles Owen
显示剩余5条评论

183

当你需要处理多个被控制的输入元素时,你可以给每个元素添加一个name属性,并让处理函数根据event.target.name的值来选择要做什么。

例如:

inputChangeHandler(event) {
  this.setState({ [event.target.name]: event.target.value });
}


9
方括号 [event.target.name] 的作用是什么?为什么它们是必需的? - user798719
1
与通常单独命名每个元素的方法相比,如下所示: this.setState({ userName: e.target.value });这种方法将表单的多个元素作为数组处理,无需设置每个单独的元素。 - vikram jeet singh
1
但是我如何以相同的方式访问该状态呢?例如 this.state([event.target.name]) - Kirankumar Dafda
1
我认为MDN web docs这篇文章解释了为什么我们需要使用方括号。 - Skelli

50

我是如何完成这个的...

inputChangeHandler: function(event) {
  var key = event.target.id
  var val = event.target.value
  var obj  = {}
  obj[key] = val
  this.setState(obj)
},

我也尝试了类似的方法,但问题是组件仍然无法渲染,我四处奔波(包括这个:D),最后在某个地方发现了这个:this.forceUpdate(); 这在最新的React中不应该出现。让我们稍后再看看问题所在吧! - xploreraj

31

我只是想补充一下,你也可以使用解构重构代码,让它看起来更整洁。

inputChangeHandler: function ({ target: { id, value }) {
    this.setState({ [id]: value });
},

15
this.setState({ [`${event.target.id}`]: event.target.value}, () => {
      console.log("State updated: ", JSON.stringify(this.state[event.target.id]));
    });
请注意引号字符。

2
正是我所需要的。 - sotn
谢谢您,这很有效。不过,能否解释一下 [ ] 是做什么用的?为什么 React 需要它? - Amon

13

我曾经遇到过类似的问题。

我想要将第二层键位的状态存储到一个变量中。

例如:this.setState({permissions[perm.code]: e.target.checked})

但是这不是有效的语法。

我使用了以下代码来实现:

this.setState({
  permissions: {
    ...this.state.permissions,
    [perm.code]: e.target.checked
  }
});

11

使用 .map 循环的工作方式如下:

{
    dataForm.map(({ id, placeholder, type }) => {
        return <Input
            value={this.state.type}
            onChangeText={(text) => this.setState({ [type]: text })}
            placeholder={placeholder}
            key={id} />
    })
}

请注意type参数中的[]。 希望这有所帮助 :)


8

我正在寻找一个美观简单的解决方案,然后我发现了这个:

this.setState({ [`image${i}`]: image })

希望这能帮到你。

4

使用 ES6+,你只需要这样写 [${variable}]。


2

当给定的元素是一个对象时:

handleNewObj = e => {
        const data = e[Object.keys(e)[0]];
        this.setState({
            anykeyofyourstate: {
                ...this.state.anykeyofyourstate,
                [Object.keys(e)[0]]: data
            }
        });
    };

希望这能对某些人有所帮助


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接