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

时间:2019-08-03 19:33:18

标签: reactjs typescript react-hooks

我有一个对象数组。我需要添加一个函数来从数组中删除对象,而无需使用“ 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>
            </>
        )}
    }

)

已执行:单击的项目将从列表中删除。
实际:系统将删除整个列表,减去数组中的最后一项。

感谢您的任何输入!

7 个答案:

答案 0 :(得分:7)

您可以使用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>
        </>
    )}

答案 1 :(得分:0)

我认为这段代码会做

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

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

Codepen

  

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

更改此视图部分

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

更改功能handleRemoveItem格式

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

答案 2 :(得分:0)

首先,带有点击事件的span元素需要具有name属性,否则,在e.target中将找不到名称。话虽如此,e.target.name保留用于表单元素(输入,选择等)。因此,要真正使用name属性,您必须使用e.target.getAttribute("name")

另外,因为您有对象数组,所以使用list.indexOf(e.target.name)无效,因为在对象上进行迭代时会寻找string。就像说在[{}, {}, {}]

中找到“狗”一样

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

使用.filter()codesandbox

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

答案 3 :(得分:0)

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

with open('config/config.json') as f:
    config = json.load(f)
API_KEY = config['API_KEY'] # loads API key

# Database info
client = MongoClient(config['HOST'], config['PORT'])
db = client[config['DATABASE']]
teams = list(db.teams.find())  # gets all the teams from the database

def list_users():
  url = 'https://api.pagerduty.com/users'
  headers = {
    'Accept': 'application/vnd.pagerduty+json;version=2',
    'Authorization': 'Token token={token}'.format(token=API_KEY)
  }
  result = []
  for team in teams:
    payload = {
        'team_ids[]': team['team_id'],
        'limit': 100,
        'offset': 0
    }
    r = requests.get(url, headers=headers, params=payload)

    users = r.json()['users']
    emails = []
    # loops for each user and retrieves their email
    for user in users:
      if r.status_code == 200:
        emails.append(user['email'])
      else:
        return None
    return emails
  return result

答案 4 :(得分:0)

您可以使用此功能从React的状态数组中删除项目,而无需更改状态。

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

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

答案 5 :(得分:0)

我认为对目前最佳答案的小改进

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 = (item) => {
    updateList(list.filter(item => item.name !== name));
  };

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

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

我们只是将其发送到句柄函数而不是提供名称属性

答案 6 :(得分:-1)

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

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

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