web-dev-qa-db-ja.com

フックを使用して配列からオブジェクトを削除する(useState)

オブジェクトの配列があります。 「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:リスト全体が削除されますが、配列の最後のアイテムは削除されます。

ご意見をお寄せいただきありがとうございます。

9
collinswade408

まず、クリックイベントのあるspan要素にはnameプロパティが必要です。それ以外の場合、_e.target_内に検索する名前はありません。つまり、_e.target.name_はフォーム要素(入力、選択など)用に予約されています。したがって、実際にnameプロパティを利用するには、e.target.getAttribute("name")を使用する必要があります

さらに、オブジェクトの配列があるため、list.indexOf(e.target.name)を使用することは効果的ではありません。オブジェクトを反復処理するときにstringを探しているためです。それは_[{}, {}, {}]_内でfind "dog"と言うようなものです

最後に、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);
_
2
Christopher Ngo

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>
        </>
    )}
7
Will Jenkins

この関数を使用して、状態を変更せずにReactの状態配列からアイテムを削除できます。

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

サンドボックス: https://codesandbox.io/s/ecstatic-goldwasser-76zop?fontsize=14

2
Dimi Mikadze

私は同じ問題に直面し、この質問の回答を使用して修正しました。ここに行くには複数の答えを使わなければならなかったので、ここに答えを入れます。

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

)
0
Mahesh Samudra

このコードはうまくいくと思います

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);
}
0
William Gunawan