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

IT技术 reactjs typescript react-hooks
2021-05-07 09:15:16

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

我尝试使用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>
            </>
        )}
    }

)

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

提前感谢您的任何意见!

4个回答

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

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

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

尝试这样的事情而不是使用.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);

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

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

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

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

我遇到了同样的问题,并使用这个问题的答案提出了一个解决方案。我把我的最终解决方案放在这里是因为我必须使用多个答案才能到达那里。

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) => (
      <div key={idx}>
        <button onClick={() => handleRemoveItem(idx)}>x </button>
        <span>{item.name}</span>
      </div>
    ))}

)

我认为这段代码会做

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

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

代码笔

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

更改此视图部分

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

更改函数handleRemoveItem格式

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