当前位置: 首页 > 知识库问答 >
问题:

如何使用setState更新状态中的state.item[1]?

上官树
2023-03-14

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

该组件在此处作为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]。名称

共有3个答案

唐高卓
2023-03-14

错了!

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

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

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

我花了一段时间才弄清楚这一点。上面是有效的,但它带走了 React 的力量。例如,组件Did更新不会将此视为更新,因为它是直接修改的。

因此,正确的方法是:

handleChange = (e) => {
    this.setState(prevState => ({
        items: {
            ...prevState.items,
            [prevState.items[1].name]: e.target.value,
        },
    }));
};
窦彦君
2023-03-14

您可以使用updateimmutability helper执行以下操作:

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

或者,如果您不关心能否使用==shouldComponentUpdate()lifecycle方法中检测到此项的更改,则可以直接编辑状态并强制组件重新呈现-这实际上与@limelights的答案相同,因为它将对象从状态中拉出来并对其进行编辑。

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

编辑后添加:

查看 react-training 中的简单组件通信课程,了解如何将回调函数从保持状态的父级传递到需要触发状态更改的子组件的示例。

柯建业
2023-03-14

以下是如何在没有辅助程序库的情况下做到这一点:

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)
    ]
}));

注意:我把项目做成了一个数组。OP 使用了一个对象。但是,概念是相同的。

您可以在终端/控制台中看到发生了什么:

❯ 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
 类似资料:
  • 我正在创建一个应用程序,用户可以在其中设计自己的表单。例如。指定字段的名称以及应包括的其他列的详细信息。 该组件在这里可以作为JSFiddle使用。 我最初的状态是这样的: 如何创建以使其更新?

  • 所以我有这个: 只是一个数组的数字例如然而没有给出正确的总数,但?我甚至放了一个超时延迟,看看这是否解决了问题。任何明显的还是我应该发布更多的代码?

  • 问题内容: 所以我有这个: newDealersDeckTotal只是一个数字数组,例如,但是没有给出正确的总数,但是呢?我什至设置了超时延迟,以查看是否可以解决问题。任何明显的还是我应该发布更多代码? 问题答案: 通常是异步的,这意味着在您处于状态时,它尚未更新。尝试将日志放入方法的回调中。状态更改完成后执行:

  • 问题内容: 我觉得我已经在阳光下尝试了所有东西,但是一定缺少一些非常明显的东西。在下面,我试图将一个新项目推入数组并更新状态,但是无论我做什么,状态都不会从初始数组更改。 当我console.log newListItems时,新项目就包括在内,因此到目前为止所有工作都在进行,它是不会更新的实际状态。我想念什么? addItem方法: 我也没有在控制台中收到任何错误消息。 完整代码: 问题答案:

  • 我正在从一个文件导出常量并将其导入另一个文件,如下所示: 常数.js App.js 我希望我的初始状态是在构造函数中设置的,然后在componentWillMount上,我希望使用常量文件中的值设置状态,然后再围绕组件和流添加进一步的逻辑。 但是,我发现,我的状态没有被更新,如果我在调用setState之后记录控制台日志,状态仍然没有定义,如果我引入一个方法,需要state中的值,那么在执行堆栈的

  • 我试图将“加载”的状态从true更改为false,但当我调用一个函数并在该函数中设置“this.setState({loading:false})”时,加载状态仍然保持true。 在下面的代码中,当按钮按钮函数被调用时,它将“加载”状态设置为真,但当用户成功登录“加载”状态时,应该变为假,这样我的渲染按钮函数将重新渲染,旋转器可以隐藏自己并显示按钮。 为什么LoginSAccess函数中的“加载”