Redux-remove item from cart

Hi, I’m trying to create remove item logic with redux. I basically tried to adapt the logic from the Favorite Recipes example, but I’m getting not a fucntion error when running the code. How can I achieve this?

export const addItem = (itemToAdd) => {
    return {
      type: 'cart/addItem',
      payload: itemToAdd,
    };
  };

  export const removeItem = (itemToRemove) => {
    return {
      type: 'cart/removeItem',
      payload: itemToRemove
    };
  };
  
  export const changeItemQuantity = (name, newQuantity ) => {
   return {
      type: 'cart/changeItemQuantity',
      payload: {
        name,
        newQuantity
      }
    }
  }
  
  
  const initialCart = {};
  export const cartReducer = (cart = initialCart, action) => {
    switch (action.type) {
      case 'cart/addItem': {
        const { name, price, img, type } = action.payload;
        
        // if the item already exists, increase the quantity by 1, otherwise set it to 1
        const quantity = cart[name] ? cart[name].quantity + 1 : 1;
        const newItem = { price, img, type, quantity };
  
        // Add the new item to the cart (or replace it if it existed already)
        return { 
          ...cart, 
          [name]: newItem 
        };
      }

      case 'cart/removeItem':
      return cart.filter(item => item.id !== action.payload.id)

      case 'cart/changeItemQuantity': {
        const { name, newQuantity } = action.payload;
        const itemToUpdate = cart[name];
        const updatedItem = {
          ...itemToUpdate,
          quantity: newQuantity
        }
        // Create a copy of itemToUpdate and update the quantity prop.
        return {
          ...cart,
          [name]: updatedItem 
        }
        // Return a copy of the cart with the updatedItem included.
        return {};
      }
      default: {
        return cart;
      }
    }
  };
import React from 'react';
import "./Cart.css";
import Navbar from './Navbar.jsx';
import { useDispatch, useSelector } from 'react-redux';
import { changeItemQuantity } from '../features/cart/cartSlice.js';
import { calculateTotal } from '../features/utilities/utilities.js';
import { removeItem } from '../features/cart/cartSlice.js';

export default function Cart() {

  const dispatch = useDispatch();
  const cart = useSelector(state => state.cart); // * Note
  
  const onInputChangeHandler = (name, input) => {
    // If the user enters a bad value...
    if (input === '') {
      return;
    }

    // Otherwise, convert the input into a number and pass it along as the newQuantity.
   const newQuantity = Number(input);

    dispatch(changeItemQuantity(name, newQuantity));

  };

  const onClickHandler = (item) => {
    dispatch(removeItem(item));
  };
  // Use the cart and currencyFilter slices to render their data.
  const cartElements = Object.entries(cart).map(createCartItem);
  const total = calculateTotal(cart);
  return (
    <>
      <Navbar/>
      <div id="cart-container">
        <ul id="cart-items">
          {cartElements == '' ? <div className="cart-empty">Your cart is empty</div> : cartElements}
        </ul>
        <h3 className="total">
          Total{' '}
          <span className="total-value">
            {total} 
          </span>
        </h3>
      </div>
    </>
  );

  function createCartItem([name, item]) {
    if (item.quantity === 0) {
      return;
    }

    return (
      <li className="cart-list" key={name}>
        <img src={item.img}/>
        <p>{name}</p>
        <p>{item.type}</p>
        <div className="quantity-container">
          <p>Quantity:</p>
          <input 
          type="number" 
          className="item-quantity" 
          name="quantity" 
          value={item.quantity}
          onChange={(e) => {
            onInputChangeHandler(name, e.target.value);
          }}/>
        </div>
        <button
            onClick={() => onClickHandler(item)}
            className="addToCart"
          >
            Remove
          </button>
      </li>
    );
  }
};

The error is probably more explicit, which line is not a function? That’s usually a clue, and you can set a breakpoint to see what type it is. Devil is in the details and all that. For example, is the type of cart an object or an array, and does an object have a built-in filter method?

1 Like

It says that cart.filter is not a function:

return cart.filter(item => item.id !== action.payload.id)

is cart an array though? You can usually trust the error messages. It probably means cart is not what you think it is or not what you’re using it as.

1 Like

It is supposed to be an empty array initially.

 const initialCart = [];

What confuses me most is that addItem works perfectly fine, but removeItem won’t. And I am using the ‘cart’ in both of those…

The point is that arrays all have the filter() method. If it is not a function it means the variable was changed from an array to something else somewhere along the way. Breakpoints are great to debug where this happens.

1 Like

one line above the cartReducer:

1 Like

I immediately corrected it in my code, but still doesn’t work.

Specificity will get the best help!

  • What is the error now? Is it the same?
  • Please use a debugger or clever logging, and try to analyze the situation from there. If you explain what you analyze from the debugging people can help you more.

You’re turning the cart into an object with this action. Then you try to filter it with the removeItem action which doesnt’ work.

What do you expect the items in the cart array to look like? What structure should they have?

In addition to the debugging recommendation by @toastedpitabread I recommend you use the redux-devtools chrome extension in order to inspect your states.

1 Like

Yes! Both regular debugging and dev tools should be something all developers are very comfortable with :slight_smile: agreed

1 Like

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.