简体   繁体   English

使用 splice() 从数组中删除对象在 React 中无法按预期工作

[英]Removing an object from array with splice() does not work as expected in React

I am creating input fields dynamically based on the number of object in my state array.我正在根据状态数组中的对象数量动态创建输入字段。 Beside each field I am adding a button to remove that field.在每个字段旁边,我添加了一个按钮来删除该字段。 However, when the button is clicked it behaves in an unexpected way.但是,当单击按钮时,它的行为出乎意料。

Below is the visual demonstration:下面是视觉演示:

When I press "Remove Option" button on " Option 0 ":当我按“选项 0 ”上的“删除选项”按钮时:

这里

The output is like :输出是这样的:

这个

However, when I see from console.log() the correct object is being removed.但是,当我从console.log()看到正确的对象被删除时。 These are console.log() outputs before:这些是之前的console.log()输出:

前

and after the above button click:在上面的按钮点击后:

后

Here is how I loop from the array in my render() :这是我如何从我的render()的数组循环:

const questions = this.state.values_array.map((question, index) => {


 return ( 
    <div key = {question.question_id}>   
    {this.state.options_array.map((option, i) => (
        option.questionID === question.question_id ? //to show only this question's options
          <div>
              <span>Option {i}:</span>
              <TextField type="text" defaultValue={option.description} />
              <span>Value:</span>
              <TextField type="number" defaultValue={option.value}/>
              <button onClick={() => this.removeOption(i)}>Remove Option</button>
          </div>
        :
          null
    ))}
    </div>
    )
  }

Here is my removeOption() method I am using to remove the input fields:这是我用来删除输入字段的removeOption()方法:

removeOption(index){

    let options = [...this.state.options_array];
    options.splice(index, 1);
    this.setState({ options_array: options });
}

And here is how I am calling it in my render's return:这是我在渲染返回中调用它的方式:

 return (
   <div>{questions}</div>
)

You are missing the keys for the div containers.您缺少div容器的键。 React needs to know which DOM Element has been removed so it re-renders it. React 需要知道哪个 DOM 元素已被删除,以便重新渲染它。 Also, do not use the index of map as the key, instead use something like the id eg option.questionID .另外,不要使用mapindex作为键,而是使用类似 id 的东西,例如option.questionID

you need to filter out the individual item from the list您需要从列表中过滤掉单个项目

removeOption(index) {
const options = this.state.options_array.filter((items, itemIndex) => itemIndex 
!== index)
this.setState({ options_array: options });}

The flaw of this approach is that in JavaScript, objects and arrays are reference types , so when we get an array, we actually get a pointer to the original array's object managed by react.这种方法的缺陷在于,在 JavaScript 中,对象和数组都是引用类型,所以当我们得到一个数组时,我们实际上得到的是一个由 react 管理的原始数组对象的指针。 If we then splice it, we already mutate the original data and whilst it does work without throwing an error, this is not really how we should do it, this can lead to unpredictable apps and is definitely a bad practice.如果我们然后拼接它,我们已经改变了原始数据,虽然它可以正常工作而不会抛出错误,但这并不是我们应该这样做的方式,这可能导致不可预测的应用程序,绝对是一种不好的做法。 A good practice is to create a copy of the array before manipulating it and a simple way of doing this is by calling the slice method.一个好的做法是在操作之前创建数组的副本,一个简单的方法是调用 slice 方法。 Slice without arguments simply copies the full array and returns a new one which is then stored.不带参数的切片只是复制完整数组并返回一个新数组,然后将其存储。 And we can now safely edit this new one and then update to react state with our new array.我们现在可以安全地编辑这个新数组,然后更新以使用我们的新数组来响应状态。 let me give you and example:让我给你和例子:

We have an array like this const arr=[1,2,3,4,5] .我们有一个像const arr=[1,2,3,4,5]这样的数组。 This is original array.这是原始数组。

As I told you before, we can do that like this:正如我之前告诉你的,我们可以这样做:

const newVar=arr.slice();
newVar.splice(Index,1);
console.log(newVar);

Or或者

An alternative to this approach would be to use it a ES6 feature, it is the Spread Operator这种方法的另一种选择是使用 ES6 特性,它是扩展运算符

Our prior code can be something like this:我们之前的代码可以是这样的:

const newVar=[...arr]
newVar.splice(Index,1);
console.log(newVar);

That's it.就是这样。 Good luck祝你好运

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM