我正在创建一个应用程序,用户可以设计自己的形式。例如,指定字段的名称和应该包括的其他列的详细信息。
该组件可作为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})}/>
如何创建另一个组件(对象,需要进入数组),并通过以下作为道具?
组件索引-索引将用于在数组中创建/更新。
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})}/>
错误的方式!
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,
},
}));
};
我将移动函数句柄change并添加一个索引参数
handleChange: function (index) {
var items = this.state.items;
items[index].name = 'newName';
this.setState({items: items});
},
到动态表单组件,并将其作为道具传递给PopulateAtCheckboxes组件。在遍历项目时,可以包含一个额外的计数器(在下面的代码中称为index),将其传递给句柄更改,如下所示
{ Object.keys(this.state.items).map(function (key, index) {
var item = _this.state.items[key];
var boundHandleChange = _this.handleChange.bind(_this, index);
return (
<div>
<PopulateAtCheckboxes this={this}
checked={item.populate_at} id={key}
handleChange={boundHandleChange}
populate_at={data.populate_at} />
</div>
);
}, this)}
最后,您可以调用更改侦听器,如下所示
<input type="radio" name={'populate_at'+this.props.id} value={value} onChange={this.props.handleChange} checked={this.props.checked == value} ref="populate-at"/>