typescript 使用钩子从数组中删除对象(useState)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/57341541/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:50:46  来源:igfitidea点击:

Removing object from array using hooks (useState)

reactjstypescriptreact-hooks

提问by collinswade408

I have an array of objects. I need to add a function to remove an object from my array without using the "this" keyword.

我有一个对象数组。我需要添加一个函数来从我的数组中删除一个对象,而不使用“this”关键字。

I tried using updateList(list.slice(list.indexOf(e.target.name, 1))). This removes everything but the last item in the array and I'm not certain why.

我尝试使用updateList(list.slice(list.indexOf(e.target.name, 1))). 这将删除数组中除最后一项之外的所有内容,我不确定为什么。

const defaultList = [
{ name: "ItemOne" },
{ name: "ItemTwo" },
{ name: "ItemThree" }]

const [list, updateList] = useState(defaultList);

const handleRemoveItem = e => {
    updateList(list.slice(list.indexOf(e.target.name, 1)))
}

return (
    {list.map(item => {
        return ( 
            <>
            <span onClick={handleRemoveItem}>x </span>
            <span>{item.name}</span>
            </>
        )}
    }

)

EXPECTED: The clicked item will be removed from the list.
ACTUAL: The entire list gets removed, minus the last item in the array.

预期:单击的项目将从列表中删除。
ACTUAL:删除整个列表,减去数组中的最后一项。

Thanks in advance for any input!

提前感谢您的任何意见!

采纳答案by Cool Guy

First of all, the spanelement with the click event needs to have a nameproperty otherwise, there will be no name to find within the e.target. With that said, e.target.nameis reserved for form elements (input, select, etc). So to actually tap into the name property you'll have to use e.target.getAttribute("name")

首先,span带有点击事件的元素需要有一个name属性,否则在e.target. 话虽如此,e.target.name保留用于表单元素(输入、选择等)。所以要真正利用 name 属性,你必须使用e.target.getAttribute("name")

Additionally, because you have an array of objects, it would not be effective to use list.indexOf(e.target.name)since that is looking for a stringwhen you are iterating over objects. That's like saying find "dog" within [{}, {}, {}]

此外,因为您有一个对象数组,所以使用它不会有效,list.indexOf(e.target.name)因为它string在您迭代对象时正在寻找 a 。这就像说在里面找到“狗”[{}, {}, {}]

Lastly, array.slice()returns a new array starting with the item at the indexyou passed to it. So if you clicked the last-item, you would only be getting back the last item.

最后,array.slice()返回一个新数组,您传递给它的索引处的项目开始。因此,如果您单击最后一项,则只会返回最后一项。

Try something like this instead using .filter(): codesandbox

尝试这样的事情而不是使用.filter()codeandbox

import React, { useState } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

const App = () => {
  const defaultList = [
    { name: "ItemOne" },
    { name: "ItemTwo" },
    { name: "ItemThree" }
  ];

  const [list, updateList] = useState(defaultList);

  const handleRemoveItem = (e) => {
   const name = e.target.getAttribute("name")
    updateList(list.filter(item => item.name !== name));
  };

  return (
    <div>
      {list.map(item => {
        return (
          <>
            <span name={item.name} onClick={handleRemoveItem}>
              x
            </span>
            <span>{item.name}</span>
          </>
        );
      })}
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

回答by Will Jenkins

You can use Array.filterto do this in a one-liner:

您可以使用Array.filter单行方式执行此操作:

const handleRemoveItem = name => {
    updateList(list.filter(item => item.name !== name))
}

Eta: you'll also need to pass the name of your item in your onClick handler:

Eta:您还需要在您的 onClick 处理程序中传递您的项目名称:

{list.map(item => {
    return ( 
        <>
        <span onClick={() =>handleRemoveItem(item.name)}>x </span>
        <span>{item.name}</span>
        </>
    )}

回答by Mahesh Samudra

I just faced the same issue and fixed using the answers in this question. I'm putting my answer here because I had to use multiple answers to get there.

我刚刚遇到了同样的问题,并使用此问题中的答案进行了修复。我把我的答案放在这里是因为我必须使用多个答案才能到达那里。

const defaultList = [
    { name: "ItemOne" },
    { name: "ItemTwo" },
    { name: "ItemThree" }
]

const [list, updateList] = useState(defaultList);

const handleRemoveItem = idx => {
    // assigning the list to temp variable
    const temp = [...list];

    // removing the element using splice
    temp.splice(idx, 1);

    // updating the list
    updateList(temp);
}

return (
    {list.map((item, idx} => {
        return ( 
            <div key={idx}>
                <span onClick={() =>handleRemoveItem(idx)}>x </span>
                <span>{item.name}</span>
            </div>
        )}
    }

)

回答by Dimi Mikadze

You can use this function to remove an item from React's state array without mutating the state.

你可以使用这个函数从 React 的 state 数组中移除一个 item 而不会改变 state。

const handleRemoveItem = name => {
  updateList(list => list.filter(item => item.name !== name));
}

Sandbox: https://codesandbox.io/s/ecstatic-goldwasser-76zop?fontsize=14

沙盒:https: //codesandbox.io/s/ecstatic-goldwasser-76zop?fontsize =14

回答by William Gunawan

I think this code will do

我认为这段代码会做

let targetIndex = list.findIndex((each) => {each.name == e.target.name});
list.splice(targetIndex-1, 1);

We need to check name value inside object so use findIndex instead. then cut the object start from target index to 1 array after target index.

我们需要检查对象内的名称值,因此请改用 findIndex。然后将对象从目标索引开始切割到目标索引后的 1 个数组。

Codepen

代码笔

From your comment your problem came from another part.

根据您的评论,您的问题来自另一部分。

Change this view section

更改此视图部分

    return ( 
        <>
        <span onClick={() => handleRemoveItem(item) }>x </span>
        <span>{item.name}</span>
        </>
    )}

change function handleRemoveItem format

更改函数handleRemoveItem格式

const handleRemoveItem = item => {
    list.splice(list.indexOf(item)-1, 1)
    updateList(list);
}

回答by Morphyish

This is because both sliceand splicereturn an array containing the removed elements.

这是因为slicesplice 都返回一个包含已删除元素的数组。

You need to apply a spliceto the array, and thenupdate the state using the method provided by the hook

您需要对splice数组应用a ,然后使用钩子提供的方法更新状态

const handleRemoveItem = e => {
    const newArr = [...list];
    newArr.splice(newArr.findIndex(item => item.name === e.target.name), 1)
    updateList(newArr)
}