我正在创建一个应用程序,用户可以设计自己的形式。例如,指定字段的名称和应该包括的其他列的详细信息。

该组件可作为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>
    );
  }
});

我该怎么做呢?setState让它更新项目[1].name ?


当前回答

如何创建另一个组件(对象,需要进入数组),并通过以下作为道具?

组件索引-索引将用于在数组中创建/更新。 set function——这个函数根据组件索引将数据放入数组中。

<SubObjectForm setData={this.setSubObjectData}                                                            objectIndex={index}/>

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

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

其他回答

首先获取您想要的项目,更改该对象上的内容并将其设置回状态。 如果你使用键控对象,你只通过在getInitialState中传递一个对象来使用状态的方式会更容易。

handleChange: function (e) {
   item = this.state.items[1];
   item.name = 'newName';
   items[1] = item;

   this.setState({items: items});
}

不要原地改变状态。它会导致意想不到的结果。我已经吸取教训了!总是使用复制/克隆,Object.assign()是一个很好的例子:

item = Object.assign({}, this.state.items[1], {name: 'newName'});
items[1] = item;
this.setState({items: items});

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

因为以上选项对我来说都不理想,所以我最终使用了map:

this.setState({items: this.state.items.map((item,idx)=> idx!==1 ?item :{...item,name:'new_name'}) })

你可以使用update immutability helper:

this.setState({
  items: update(this.state.items, {1: {name: {$set: 'updated field name'}}})
})

或者,如果您不关心是否能够使用===在shouldComponentUpdate()生命周期方法中检测该项的更改,那么您可以直接编辑状态并强制组件重新呈现—这实际上与@limelights的答案相同,因为它将对象拉出状态并编辑它。

this.state.items[1].name = 'updated field name'
this.forceUpdate()

后编之外:

请参阅react-training中的简单组件通信课程,了解如何将回调函数从持有状态的父组件传递给需要触发状态更改的子组件。

尝试代码:

this.state.items[1] = 'new value';
var cloneObj = Object.assign({}, this.state.items);

this.setState({items: cloneObj });