Search code examples
reactjsreduxreact-redux

Why Redux removes all elements from cart instead one?


I'm making simple ecommerce service using React and classic Redux. I have problem with deleting items from cart. When I click delete on button attached to one products it removes all elements from cart.

In my opinion code is correct, I compared it with few other solutions I've found on SO. I'd be glad for any tips.

Here is my code:

Initial state

initialState: {
    cart: {
      products: [],
    },
}

Product in cart with delete function (props here is an object with product details)

const ProductInCart = (props) => {

  const dispatch = useDispatch();
  const productId = props.id;

  console.log(productId)

  const handleDelete = e => {
    e.preventDefault();
    dispatch(deleteProduct(productId))
  }

  return (
    <div className={styles.product__item}>

      <Link to={`/product/${props.id}`} className={styles.link}>
        <div className={styles.leftColumn}>
          <img 
            src={`${process.env.PUBLIC_URL}${props.img}`} 
            alt="Product image" 
          />
          <div className={styles.info}>
            <h3>{props.title}, {props.width} cm x {props.height} cm</h3>
            <p>Color: {props.color}</p>
          </div>
        </div>
      </Link>

      <div className={styles.rightColumn}>
        <div className={styles.delete} onClick={handleDelete}>
          <DeleteIcon className={styles.icon}/>
          <span>Delete</span>
        </div>
        <div className={styles.quantity}>
          <h2>Quantity:</h2>
          <Quantity />
        </div>
        <span className={styles.price}>${props.price}</span>
      </div>
    </div>
  )
}

And here is my reducer

// selectors
export const getAll = ({ cart }) => cart.products;
export const getCount = ({ cart }) => cart.products.length;

// action name creator
const createActionName = actionName => `app/cart/${actionName}`;

// action types
const ADD_PRODUCT = createActionName('ADD_PRODUCT');
const DELETE_PRODUCT = createActionName('DELETE_PRODUCT');

// action creators
export const addProduct = payload => ({ payload, type: ADD_PRODUCT});
export const deleteProduct = payload => ({ payload, type: DELETE_PRODUCT});

// reducer
const cartReducer = (statePart = [], action ={}) => {

  switch (action.type) {
    case ADD_PRODUCT: {
      return {
        ...statePart,
        products: [...statePart.products, action.payload]
      }
    }
    case DELETE_PRODUCT: {
      return statePart.products.filter(product => product.id !== action.payload)
    }
    default:
      return statePart;
  }
}

export default cartReducer;

Solution

  • you should return a new state like your ADD_PRODUCT case

    case DELETE_PRODUCT: {
      return {
        ...statePart,
        products: statePart.products.filter(product => product.id !== action.payload)
      }
    }