ReactJS - 如何在函数式组件中从数组中删除一个项目?

3

我尝试使用ReactJS创建一个简单的购物车,我找到了一种潜在的解决方案,但是当我点击我设定的删除按钮时,它并没有真正将商品从购物车中删除... 这是我的状态管理器:

let[product, setProduct] = useState([])
//The function bellow is what I use to render the products to the user
const[item] = useState([{
        name: 'Burger',
        image: '/static/media/Burger.bcd6f0a3.png',
        id: 0,
        price: 16.00
    },
    {
        name: 'Pizza',
        image: '/static/media/Pizza.07b5b3c1.png',
        id: 1,
        price: 20.00
    }])

我有一个函数,可以将item中的对象添加到product数组中,然后我有一个函数,应该从中删除它们,看起来像这样:

    const removeItem=(idx)=>
{
    // let newProduct = product.splice(idx,1)
    // setProduct([product,newProduct])
    // $('.showItems').text(product.length)
    // product[idx]=[]
    product.splice(idx,1)

    if(product.length<=0)
    {
        $('.yourCart').hide()
    }
}

这个函数被从这里调用:

                    {product.map((item, idx)=>
                <div className='yourCart' key={idx}>
                    <hr></hr>
                    <div>
                        <img src ={item.image}></img>
                        <h3 className='burgerTitle'>{item.name}</h3>
                        <h4><strong>$ {item.price}.00</strong></h4>
                        <Button variant='danger' onClick={()=>removeItem(idx)}>Remove</Button>
                    </div>
                    <br></br>
              </div>)}

问题在于我尝试使用splice、setState,甚至尝试清空整个数组并将过滤函数应用后留下的元素添加到其中,但都没有成功。 当我点击删除按钮时,如何使其从数组中删除特定项?


您正在通过直接调用splice来改变状态。如果这是您要采取的路线,您可以将回调函数传递给setState setProduct(prevProduct => prevProduct.splice()) - pilchard
@pilchard嘿,谢谢你的快速回复!!乍一看似乎工作正常,但是每当我添加多个产品并且点击删除第二个或第三个产品时,它会删除整个产品列表。这是为什么? - Python_Mython79
你仍然需要将你的 (idx, 1) 传递给 splice,但是使用 id 而不是它是更健壮的解决方案。 - pilchard
2个回答

4
您可以将removeItem定义为一个函数,该函数获取一个id(而不是索引,因为这更安全),并将setProduct设置为应保留的子集。这可以通过多种方式实现,在此特定示例中,我使用.filter()查找与要删除的元素的id不同的product的子集,并将结果设置为product的新值。
removeItem = (id) => {
  setProduct(product.filter((i)=>(i.id !== id)))
 
}

2
你好,欢迎来到SO。像这样的仅包含代码的答案价值有限,需要解释问题/解决方案、你所做出的假设等等。例如,如果你选择不使用splice,可以详细说明原因。 - Avius
我喜欢这个答案,直戳要害! - Python_Mython79

3
你需要使用useState钩子提供的mutation方法setProduct来改变product状态。
const removeItem = (id) => {
    const index = product.findIndex(prod => prod.id === id); //use id instead of index
    if (index > -1) { //make sure you found it
     setProduct(prevState => prevState.splice(index, 1));
    }   
}

使用方法

<Button variant='danger' onClick={()=>removeItem(item.id)}>Remove</Button>

作为一个附带说明: 在处理数组中的项目时,考虑使用确定的 id 值而不是数组中的索引。项目的索引可能会发生变化。在映射时使用 item.id 作为键,而不是索引。考虑使用 guid 作为标识。[点击此处]
{product.map((item, idx)=>
  <div className='yourCart' key={`cartItem_${item.id}`}> //<-- here
      <hr></hr>
      <div>
          <img src ={item.image}></img>
          <h3 className='burgerTitle'>{item.name}</h3>
          <h4><strong>$ {item.price}.00</strong></h4>
          <Button variant='danger' onClick={()=>removeItem(item.id)}>Remove</Button>
      </div>
      <br></br>
</div>)}

同时,在 const index = product.findIndex(prod => prod.id === id); 这行代码中,prod.id 是如何获取它的值的? - Python_Mython79
我假设您将item状态中的项目添加到购物车时将其推送到product中。每个item对象都有一个id属性,因此您的产品项也会有。findIndex将为数组中的每个项目调用括号内的函数(prod => prod.id === id)。在此处查看更多信息:https://www.w3schools.com/jsref/jsref_findindex.asp#:~:text=The%20findIndex()%20method%20executes,Otherwise%20it%20returns%20%2D1 - GBourke
明白了!谢谢! - Python_Mython79

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接