我正在创建一个应用程序,用户可以在其中设计自己的表单。例如,指定字段的名称和应包含的其他列的详细信息。
该组件在此处作为 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?
this.setState
items[1].name
由于该线程中有很多错误信息,因此您可以在没有帮助库的情况下执行以下操作:
handleChange: function (e) { // 1. Make a shallow copy of the items let items = [...this.state.items]; // 2. Make a shallow copy of the item you want to mutate let item = {...items[1]}; // 3. Replace the property you're intested in item.name = 'newName'; // 4. Put it back into our array. N.B. we *are* mutating the array here, but that's why we made a copy first items[1] = item; // 5. Set the state to our new copy this.setState({items}); },
如果需要,您可以组合步骤 2 和 3:
let item = { ...items[1], name: 'newName' }
或者您可以在一行中完成整个操作:
this.setState(({items}) => ({ items: [ ...items.slice(0,1), { ...items[1], name: 'newName', }, ...items.slice(2) ] }));
注意:我做了items一个数组。OP使用了一个对象。但是,概念是相同的。
items
您可以在终端/控制台中看到发生了什么:
>node > items = [{name:'foo'},{name:'bar'},{name:'baz'}] [ { name: 'foo' }, { name: 'bar' }, { name: 'baz' } ] > clone = [...items] [ { name: 'foo' }, { name: 'bar' }, { name: 'baz' } ] > item1 = {...clone[1]} { name: 'bar' } > item1.name = 'bacon' 'bacon' > clone[1] = item1 { name: 'bacon' } > clone [ { name: 'foo' }, { name: 'bacon' }, { name: 'baz' } ] > items [ { name: 'foo' }, { name: 'bar' }, { name: 'baz' } ] // good! we didn't mutate `items` > items === clone false // these are different objects > items[0] === clone[0] true // we don't need to clone items 0 and 2 because we're not mutating them (efficiency gains!) > items[1] === clone[1] false // this guy we copied