Home > other >  .splice method removes extra elements in a list - ReactJS
.splice method removes extra elements in a list - ReactJS

Time:07-29

I'm trying to make a shopping cart, the list of items contains different objects and each object has an id. It starts from 1 and ends on 9 (9 objects are there in the list.).

ex -

 {
    id: 1,
    title: "Buttermilk Pancakes",
    category: "breakfast",
    price: 15.99,
    img: "./images/item-1.jpeg",
    desc: `I'm baby woke mlkshk wolf bitters live-edge blue bottle, hammock freegan copper mug whatever cold-pressed `,
  },

So, calling the dispatch with action type = "REMOVE" gets the item's id. (In the payload I'm fetching the id attribute. )

Now I have the item's ID, but I'm trying to find a way to filter out just one instance of that ID (The cart could have the same item, added twice. If there are more than 1 items of the same type, it just shows up as a new item.) from the "state" array (the array that contains the current items in the cart).

But I can't find a way to remove just one instance of that item with the key/id of the item from the state array. I have tried using splice(index,1) but it still removes extra elements.

Here is the code - (Removed import lines that are not related to the issue.)

import { useReducer, useState } from "react";

export const CartValue = React.createContext();

function App() {
  const [totalCartValue, setTotalCartValue] = useState(0);

  const reducer = (state, action) => {
    const item = menu[action.payload - 1];
    switch (action.type) {
      case "ADD":
        setTotalCartValue(totalCartValue   item.price);
        return [...state, item];

      case "REMOVE":
        setTotalCartValue(totalCartValue - item.price);
        state.splice(action.payload - 1, 1);
        return state;

      default:
        throw new Error();
    }
  };
  const [state, dispatch] = useReducer(reducer, []);

  return (
    <>
      <CartValue.Provider value={{ reducer, dispatch, state, totalCartValue }}>
        <Home></Home>
        <Menu></Menu>
        <Story></Story>
        <Contact></Contact>
        <Footer></Footer>
      </CartValue.Provider>
    </>
  );
}

export default App;

Here is the map function that creates the cart list. (this is from a different component that is accessing the dispatch function with the use of use context.) -

{state.map((item) => {
        const { id, title, price } = item;

        return (
          <div className="cartItem" key={id}>
            <div className="cartItemDetails btnCommonDesign">
              <p className="itemName">{title}</p>

              <button
                className="deleteCartItem"
                onClick={() => {
                  dispatch({ type: "REMOVE", payload: id });
                }}
              >
                <AiOutlineDelete size={18} />
              </button>
            </div>

            <span className="cartItemPrice">${price}</span>
          </div>
        );
      })}

CodePudding user response:

Splice works with array indexes and you are passing id property of item object. Instead you could pass the actual index of the item

/* Use index from map function and pass that as payload */

{
  state.map((item, idx) => {
    const { id, title, price } = item;

    return (
      <div className="cartItem" key={id}>
        <div className="cartItemDetails btnCommonDesign">
          <p className="itemName">{title}</p>

          <button
            className="deleteCartItem"
            onClick={() => {
              dispatch({ type: "REMOVE", payload: idx });
            }}
          >
            <AiOutlineDelete size={18} />
          </button>
        </div>

        <span className="cartItemPrice">${price}</span>
      </div>
    );
  });
}

In your reducer function you can do this for case "REMOVE"

case "REMOVE":
        setTotalCartValue(totalCartValue - item.price);

        /* Instead of mutating original array you could create a copy of
        that array and splice on it and return it in the state. */

        const indexOfItemToBeRemoved = action.payload
        const cart = [...state]
        cart.splice(indexOfItemToBeRemoved, 1);
        return [...cart];

  • Related