简体   繁体   English

在反应中从状态数组中删除项目

[英]Deleting item from state array in react

I have a delete function that looks like this:我有一个像这样的删除函数:

   this.deleteItem = item => event => {
      const { res, selectedItems } = this.state;
      res.splice(res.indexOf(item), 1);
      selectedItems.splice(res.indexOf(item), 1);

      this.setState({
        res
      });
    };

Here, the res is the list of items displayed on the page, and selectedItems is a list of which of those items are selected.这里, res是页面上显示的项目列表, selectedItemsselectedItems了哪些项目的列表。 When an item from res is deleted, selectedItems should be updated to remove the index of that item from the list.res的项目被删除时,应更新selectedItems以从列表中删除该项目的索引。

Whenever I try to delete a specific item however, it just deletes the last item added to the array, rather than the item that corresponds to the index of the target clicked.但是,每当我尝试删除特定项目时,它只会删除添加到数组中的最后一个项目,而不是与单击的目标索引对应的项目。 Something must be going on with the way it's being indexed, but I've been having trouble identifying the source.索引的方式一定有问题,但我一直无法确定来源。

I've also tried as referenced here , but this didn't work since I need to take in item as a parameter.我也尝试过参考here ,但这不起作用,因为我需要将item作为参数。

What would be a good way to go about this?什么是解决这个问题的好方法?

Thank you very much.非常感谢。

EDIT: Changed the function to look like @HMK's response.编辑:将函数更改为看起来像@HMK 的响应。 After an item is deleted, the output of console.log(res) in the render method is an array of objects which has the form:删除项目后,render 方法中console.log(res)的输出是一个对象数组,其形式如下:

res 
(9) […]
​
0: Object { id: 0, name: "a", description: "description of a", … }
​
1: Object { id: 2, name: "b", description: "description of b", … }
​
2: Object { id: 3, name: "c", description: "description of c", … }
​
3: Object { id: 4, name: "d", description: "description of d", … }
​
4: Object { id: 5, name: "e", description: "description of e", … }
​
5: Object { id: 6, name: "f", description: "description of f", … }
​
6: Object { id: 7, name: "g", description: "description of g", … }
​
7: Object { id: 8, name: "h", description: "description of h", … }
​
8: Object { id: 9, name: "i", description: "description of i", … }
​
length: 9
​
<prototype>: Array []

The output of console.log(JSON.stringify(item,undefined,2)); console.log(JSON.stringify(item,undefined,2)); in the deleteItem function is the object that is deleted from the array.deleteItem函数中是从数组中删除的对象。

eg:例如:

{
  "id": 10,
  "name": "j",
  "description": "description of j",
  "icon": "jIcon",
  "selected": false
}

When all items on the page are selected, the output of console.log("selecteditems:", JSON.stringify(selectedItems)) :当页面上的所有项目都被选中时, console.log("selecteditems:", JSON.stringify(selectedItems))

selecteditems: [0,1,2,3,4,5,6,7,8,9,10]

To take out an item from an array you can do the following:要从数组中取出一个项目,您可以执行以下操作:

array.filter(item=>item!==itemToRemove)

So in your example:所以在你的例子中:

this.deleteItem = item => event => {
  const filter = getter => val => getter(val) !== item.id
  this.setState({
    res: this.state.res.filter(filter(({id})=>id)),
    selectedItems: this.state.selectedItems.filter(
      filter(id=>id)
    )
  })
}

The problem you have is that res stores an array of objects that have an id (for example: [{id:1}] , then selectedItems is an array that stores the id: (for example: [1]).您遇到的问题是 res 存储具有 id 的对象数组(例如: [{id:1}] ,然后 selectedItems 是存储 id 的数组:(例如:[1])。

Array.prototype.filter works in the following way: newArray = array.filter(filterFunction) . Array.prototype.filter 的工作方式如下: newArray = array.filter(filterFunction) For each item in array filterFunction is called with that item.对于数组 filterFunction 中的每个项目,都会使用该项目调用。 If filterFunction returns false then that item is not copied to newArray , it it returns true it is copied to newArray.如果 filterFunction 返回false则该项目不会被复制到newArray ,它返回 true 它被复制到 newArray 。 The original array stays untouched (as it should be with state because you should not mutate it).原始数组保持不变(因为它应该带有状态,因为你不应该改变它)。

So the problem is that your filter function gets an item of the array, decides if it should return true or false (true to keep the item and false to not keep it).所以问题是你的过滤器函数获取数组的一个项目,决定它是否应该返回 true 或 false(true 保留该项目,false 不保留它)。 So if I filter res the filter function will receive {id:X} (object with an id) but when I filter selectedItems I will receive X (the id ).因此,如果我过滤res过滤器函数将收到{id:X} (带有 id 的对象),但是当我过滤selectedItems我将收到Xid )。

So the filter function needs to take out element(s) with a certain id, however;因此,过滤器功能需要取出具有特定 id 的元素; with res that id is a property of an object and with selectedItems it is an id. res表示 id 是一个对象的属性,而selectedItems它是一个 id。 For res you can write a getter function to get the id out of the object: resItem=>resItem.id , give that function an item from res and it'll return an id.对于res您可以编写一个 getter 函数来从对象中获取 id: resItem=>resItem.id ,从res为该函数提供一个项目,它将返回一个 id。 For selectedItems the getter function should just return the value it's given because items in selectedItems are ids, so that getter function looks like id=>id对于selectedItems ,getter 函数应该只返回它给定的值,因为selectedItems中的项目id,因此 getter 函数看起来像id=>id

Ok, lets' get back to filter, I have an array of id's called selectedItems [9] and want to remove id with value 9, let's call that idToRemove so I can do: selectedItems.filter(id=>id!==idToRemove) .好的,让我们回到过滤器,我有一个名为selectedItems [9] 的 id 数组,想要删除值为 9 的 id,让我们调用 idToRemove 以便我可以这样做: selectedItems.filter(id=>id!==idToRemove) That same function won't work with res because {id:9} never equals 9 .相同的函数不适用于res因为{id:9}永远不等于9

But what if I pass a selector to the filter function, here it gets a bit complicated because functions can return a function:但是如果我将一个选择器传递给过滤器函数,这里会变得有点复杂,因为函数可以返回一个函数:

 const idToRemove = 9; //filter function return true for array item to stay in the copied array // and false to not include the array item in the copy const filter = getter => arrayItem => getter(arrayItem) !== idToRemove; //passing filter a getter function will return a function that takes // an item and uses the getter function on that item to compare it // to idToRemove const compareId = filter(id => id); console.log('keep 9?', compareId(9)); console.log('keep 8?', compareId(8)); //now create a filter function that takes an object and uses // the getter to get object.id and compares that to idToRemove const compareObjectWithId = filter(object => object.id); console.log('keep {id:9}?', compareObjectWithId({ id: 9 })); console.log('keep {id:8}?', compareObjectWithId({ id: 8 }));

So compareId is a function we can use to filter out an item from selectedItems and compareObjectWithId is a function we can use to filter out an item from res here is how the filter is used:所以compareId是一个函数,我们可以用来从selectedItems过滤出一个项目, compareObjectWithId是一个我们可以用来从res过滤出一个项目的函数,这里是过滤器的使用方式:

 const idToRemove = 9; const createFilterFunction = getter => arrayItem => getter(arrayItem) !== idToRemove; console.log( '[2,9] remove id 9', [2, 9].filter(createFilterFunction(id => id)) ); console.log( '[{id:2},{id:9}] remove id 9', [{ id: 2 }, { id: 9 }].filter( createFilterFunction(object => object.id) ) );

For completion I will add modern code to remove a key from an object (don't try this on stack overflow code snippet because it's using an ancient babel version)为了完成,我将添加现代代码来从对象中删除一个键(不要在堆栈溢出代码片段上尝试这个,因为它使用的是古老的 babel 版本)

const org = {a:1,b:2};
const withoutA = Object.fromEntries(
  Object.entries(org).filter(([key])=>key!=='a')//removed key 'a'
)

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

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