4

I want to remove object from my list by clicking on delete icon, but with my logic either everything is deleted from list or nothing, I am not sure how to do it without provided ID to object, I don't have anything unique and I am kinda lost. Component that renders as many Food as there is in useState:

 {cartFood.map((food) => {
    return (
      <CartFood
         key={Math.random()}
         foodName={food.foodName}
         foodPrice={food.foodPrice}
         numberOfPortions={food.numberOfPortions}
         cartFood={cartFood}
         setCartFood={setCartFood}
      />
    );
 })}

Logic for removing that particular item that is selected (which is not working and also bad solution since there can be case where you get same name and price twice)

const CartFood = ({
  foodName,
  foodPrice,
  numberOfPortions,
  cartFood,
  setCartFood,
}) => {
  const handleRemoveFood = () => {
    setCartFood(
      cartFood.filter(
        (el) =>
          el.foodName &&
          el.foodPrice !== cartFood.foodName &&
          cartFood.foodPrice
      )
    );
  };

  return (
    <div className='cartFood-container'>
      <p>{foodName}</p>
      <p>x{numberOfPortions}</p>
      <p>{foodPrice}kn</p>
      <p>
        <MdDeleteForever
          className='cartFood__icon'
          onClick={handleRemoveFood}
        />
      </p>
    </div>
  );
};

export default CartFood;

List of objects looks like this:

[{
  foodName: "Njoki with sos"
  foodPrice: 35
  numberOfPortions: 1
}, 
{
  foodName: "Chicken Wingos"
  foodPrice: 45
  numberOfPortions: 2
}]
2
  • You think of this const [cartFood, setCartFood] = useState([]); or something else? Commented Oct 6, 2020 at 14:52
  • As long as your list items aren't overly large and your list is very long, you can also just compare the list items as string: cartFood.filter((el) => JSON.stringify(el) !== JSON.stringify(cartFood)) Commented Oct 6, 2020 at 15:00

3 Answers 3

3
  • Put the index of the item in the array as the id. Pass it as your id.
 {cartFood.map((food, index) => {
              return (
                <CartFood
                  key={index}
                  id={index}
                  foodName={food.foodName}
                  foodPrice={food.foodPrice}
                  numberOfPortions={food.numberOfPortions}
                  cartFood={cartFood}
                  setCartFood={setCartFood}
                />
              );
            })}
  • Use the id to remove the food.
const CartFood = ({
  foodName,
  foodPrice,
  numberOfPortions,
  cartFood,
  setCartFood,
  id,
}) => {
  const handleRemoveFood = () => {
    setCartFood(cartFood.filter((el) => el.id !== id));
  };

  return (
    <div className='cartFood-container'>
      <p>{foodName}</p>
      <p>x{numberOfPortions}</p>
      <p>{foodPrice}kn</p>
      <p>
        <MdDeleteForever
          className='cartFood__icon'
          onClick={handleRemoveFood}
        />
      </p>
    </div>
  );
};

Sign up to request clarification or add additional context in comments.

9 Comments

Hm... I think I messed up something since ur soultion should work but everything from cart is removed, not just that specific item...
Yes, I tried to suggest edit but I couldint since it is only one charachter, problem continues, everything is removed from cart, and not only specific item, is it possible I messed something else? Do I need to spread something, maybe?
Do check again, the code should work. I've updated. You need to check the id which comes as the prop in your filter function.
@PrateekThapa It is not recommended to use indexes for keys if the order of items may change: medium.com/@robinpokorny/…
|
2

Something like this should work :

const handleRemoveFood = (obj) => {
        setCartFood((oldList) => oldList.filter((item) => item.foodName !== obj.foodName));
    };

Your button (icon) should call this function with current object data (obj)

A working example : https://codesandbox.io/s/cart-isz6c?file=/index.js

2 Comments

I updated my code with @Prateek's solution, can I use id on function you showed here?
I tried, still same, nothing happens, that specific items still stay in cart, I dont know whats wrong...
1

From what I see in your repo:

  1. Just pass the food._id to FoodCard so you access it when you want to add or remove an item from cart:

FoodList.js

const foodList = (typeOfList) =>
  typeOfList.map(food => {
    return (
      <FoodCard
        key={food._id}
        foodId={food._id}
        foodName={food.title}
        foodPrice={food.price}
        foodPic={food.image}
        setCartFood={setCartFood}
        cartFood={cartFood}
      />
    );
  });

FoodCard.js

const handleAddToCard = () => {
    setCartFood([
      ...cartFood,
      {
        foodId,
        foodName,
        foodPrice,
        numberOfPortions,
      },
    ]);
  };

CartFood.js

const handleRemoveFood = () => {
    setCartFood(cartFood => cartFood.filter((el) => el.foodId !== foodId));
  };

Working example:

Edit crazy-browser-fhw9m

  1. You could use useReducer with useContext so you don't have to pass props down manually at every level, check this article for more info

  2. You don't need to pass the cartFood as a property just for updating the state since you can use setState callback:

setCartFood(cartFood => [
      ...cartFood,
      {
        foodId,
        foodName,
        foodPrice,
        numberOfPortions,
      },
    ]);

1 Comment

Hm...I opened your example on codesandbox but when I wanna delete item from cart nothing happens :/ p.s. Thanks for article definetly gonna read it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.