web-dev-qa-db-fra.com

Suppression d'un objet du tableau à l'aide de crochets (useState)

J'ai un tableau d'objets. J'ai besoin d'ajouter une fonction pour supprimer un objet de mon tableau sans utiliser le mot-clé "this".

J'ai essayé d'utiliser updateList(list.slice(list.indexOf(e.target.name, 1))). Cela supprime tout sauf le dernier élément du tableau et je ne sais pas pourquoi.

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

)

ATTENDU: l'élément cliqué sera supprimé de la liste.
RÉEL: La liste entière est supprimée, moins le dernier élément du tableau.

Merci d'avance pour toute contribution!

9
collinswade408

Tout d'abord, l'élément span avec l'événement click doit avoir une propriété name sinon, il n'y aura pas de nom à trouver dans le e.target. Cela dit, e.target.name Est réservé aux éléments de formulaire (entrée, sélection, etc.). Donc, pour exploiter la propriété name, vous devrez utiliser e.target.getAttribute("name")

De plus, étant donné que vous disposez d'un tableau d'objets, il ne serait pas efficace d'utiliser list.indexOf(e.target.name) car il recherche un string lorsque vous parcourez des objets. C'est comme dire de trouver "chien" dans [{}, {}, {}]

Enfin, array.slice() renvoie un nouveau tableau commençant par l'élément à l'index que vous lui avez transmis. Donc, si vous cliquez sur le dernier élément, vous ne récupérerez que le dernier élément.

Essayez quelque chose comme ça à la place en utilisant .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

Vous pouvez utiliser Array.filter pour le faire dans une ligne:

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

Eta: vous devrez également passer le nom de votre article dans votre gestionnaire onClick:

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

Vous pouvez utiliser cette fonction pour supprimer un élément du tableau d'état de React sans muter l'état.

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

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

2
Dimi Mikadze

Je viens de faire face au même problème et corrigé en utilisant les réponses à cette question. Je mets ma réponse ici parce que j'ai dû utiliser plusieurs réponses pour y arriver.

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

Je pense que ce code fera l'affaire

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

Nous devons vérifier la valeur du nom à l'intérieur de l'objet, utilisez plutôt findIndex. puis coupez le début de l'objet de l'index cible à 1 tableau après l'index cible.

Codepen

D'après votre commentaire, votre problème vient d'une autre partie.

Modifier cette section de vue

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

changer la fonction handleRemoveItem format

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