反应:如何使用setState更新state.item \[1\]状态?

JavaScript

SamJinJin

2020-03-10

我正在创建一个应用程序,用户可以在其中设计自己的表单。例如,指定字段名称以及应包括哪些其他列的详细信息。

该组件在此处可作为JSFiddle使用

我的初始状态如下:

var DynamicForm = React.createClass({
  getInitialState: function() {
   var items = {};
   items[1] = { name: 'field 1', populate_at: 'web_start',
                same_as: 'customer_name',
                autocomplete_from: 'customer_name', title: '' };
   items[2] = { name: 'field 2', populate_at: 'web_end',
                same_as: 'user_name', 
                    autocomplete_from: 'user_name', title: '' };

     return { items };
   },

  render: function() {
     var _this = this;
     return (
       <div>
         { Object.keys(this.state.items).map(function (key) {
           var item = _this.state.items[key];
           return (
             <div>
               <PopulateAtCheckboxes this={this}
                 checked={item.populate_at} id={key} 
                   populate_at={data.populate_at} />
            </div>
            );
        }, this)}
        <button onClick={this.newFieldEntry}>Create a new field</button>
        <button onClick={this.saveAndContinue}>Save and Continue</button>
      </div>
    );
  }

我想在用户更改任何值时更新状态,但是我很难定位正确的对象:

var PopulateAtCheckboxes = React.createClass({
  handleChange: function (e) {
     item = this.state.items[1];
     item.name = 'newName';
     items[1] = item;
     this.setState({items: items});
  },
  render: function() {
    var populateAtCheckbox = this.props.populate_at.map(function(value) {
      return (
        <label for={value}>
          <input type="radio" name={'populate_at'+this.props.id} value={value}
            onChange={this.handleChange} checked={this.props.checked == value}
            ref="populate-at"/>
          {value}
        </label>
      );
    }, this);
    return (
      <div className="populate-at-checkboxes">
        {populateAtCheckbox}
      </div>
    );
  }
});

我应该如何this.setState进行更新items[1].name

第481篇《反应:如何使用setState更新state.item \[1\]状态?》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

7个回答
A梅 2020.03.10

如何创建另一个组件(对于需要进入数组的对象)并将以下内容作为道具传递呢?

  1. 组件索引-索引将用于在数组中创建/更新。
  2. set函数-此函数根据组件索引将数据放入数组。
<SubObjectForm setData={this.setSubObjectData}                                                            objectIndex={index}/>

这里可以根据使用此SubObjectForm的位置传递{index}。

和setSubObjectData可以是这样的。

 setSubObjectData: function(index, data){
      var arrayFromParentObject= <retrieve from props or state>;
      var objectInArray= arrayFromParentObject.array[index];
      arrayFromParentObject.array[index] = Object.assign(objectInArray, data);
 }

在SubObjectForm中,可以在更改数据时调用this.props.setData,如下所示。

<input type="text" name="name" onChange={(e) => this.props.setData(this.props.objectIndex,{name: e.target.value})}/>
理查德小哥 2020.03.10
 handleChanges = (value, key) => {
     // clone the current State object
    let cloneObject = _.extend({}, this.state.currentAttribute);
    // key as user.name and value= "ABC" then current attributes have current properties as we changes
    currentAttribute[key] = value;
    // then set the state "currentAttribute" is key and "cloneObject" is changed object.  
    this.setState({currentAttribute: cloneObject});

并从文本框中更改添加onChange事件

onChange = {
   (event) => {                                                
      this.handleChanges(event.target.value, "title");
   }
}
樱小胖Mandy 2020.03.10

使用事件on handleChange找出已更改的元素,然后对其进行更新。为此,您可能需要更改一些属性以进行标识和更新。

参见小提琴https://jsfiddle.net/69z2wepo/6164/

Near神乐路易 2020.03.10

在我沉闷的头脑中,遵循以下代码很容易。删除对象并替换为更新的对象

    var udpateditem = this.state.items.find(function(item) { 
                   return item.name == "field_1" });
    udpateditem.name= "New updated name"                       
    this.setState(prevState => ({                                   
    items:prevState.dl_name_template.filter(function(item) { 
                                    return item.name !== "field_1"}).concat(udpateditem)
    }));
泡芙Gil 2020.03.10

根据关于setState的React文档Object.assign按照此处其他答案的建议使用不是理想的。由于setState异步行为的性质,使用此技术的后续调用可能会覆盖先前的调用,从而导致不良后果。

相反,React docs建议使用更新器形式,setState形式在先前状态下运行。请记住,在更新数组或对象时,您必须返回一个新的数组或对象,因为React要求我们保持状态不变性。使用ES6语法的spread运算符浅表复制数组,在数组的给定索引处创建或更新对象的属性,如下所示:

this.setState(prevState => {
    const newItems = [...prevState.items];
    newItems[index].name = newName;
    return {items: newItems};
})
阿飞蛋蛋 2020.03.10

错误的方法!

handleChange = (e) => {
    const { items } = this.state;
    items[1].name = e.target.value;

    // update state
    this.setState({
        items,
    });
};

正如许多更好的开发人员在评论中指出的:改变状态是错误的!

花了我一段时间来解决这个问题。以上工作,但它带走了React的力量。例如,componentDidUpdate由于它是直接修改的,因此不会将其视为更新。

因此正确的方法是:

handleChange = (e) => {
    this.setState(prevState => ({
        items: {
            ...prevState.items,
            [prevState.items[1].name]: e.target.value,
        },
    }));
};
樱Itachi 2020.03.10

我有同样的问题。这是一个可行的简单解决方案!

const newItems = [...this.state.items];
newItems[item] = value;
this.setState({ items:newItems });

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android