I am trying to get total price of items added and removed in Cart, but total just increase and no decrease when remove one item.
I'm working with reducer and I am almost sure that I've implemented here the logic but I'm very stuck in this trouble.
This is my code reducer in CartRedux.js
const cartSlice = createSlice({
name: "cart",
initialState: {
products: [],
quantity: 0,
total: 0,
},
reducers: {
addProduct: (state, action) => {
state.quantity += 1;
state.products.push((product) => product._id === action.payload);
state.total += action.payload.price * action.payload.quantity;
},
clearCart: (state) => {
state.products = [];
},
deleteProductStart: (state) => {
state.isFetching = true;
state.error = false;
},
deleteProductSuccess: (state, action) => {
state.isFetching = false;
state.quantity -= 1;
state.products.splice(
state.products.findIndex((item) => item._id === action.payload),
1
);
//agregar aquí la función para restar el total en el RESUMEN DE COMPRA
},
deleteProductFailure: (state) => {
state.isFetching = false;
state.error = true;
},
}
});
The deleteProductSuccess
case reducer isn't computing/recomputing a total, but instead is only adjusting the total quantity.
Both quantity
and total
are what would be considered derived "state", meaning these are easily computed values from actual state, and don't generally belong as part of the state as it's considered a React anti-pattern. The suggestion here is to instead store just the products
array and compute the derived state the cart.products
array.
Example:
const cartSlice = createSlice({
name: "cart",
initialState: {
products: [],
},
reducers: {
addProduct: (state, action) => {
const item = state.products.find((product) => product._id === action.payload.id);
if (item) {
item.quantity += action.payload.quantity;
} else {
state.products.push(action.payload);
}
},
clearCart: (state) => {
state.products = [];
},
deleteProductStart: (state) => {
state.isFetching = true;
state.error = false;
},
deleteProductSuccess: (state, action) => {
state.isFetching = false;
state.products.splice(
state.products.findIndex((item) => item._id === action.payload.id),
1
);
},
deleteProductFailure: (state) => {
state.isFetching = false;
state.error = true;
},
}
});
// Note: the selector functions need to access the correct state from root.
// This is dictated by how you combine reducers and structure the reducer tree.
// This is just an example since I've no idea what the overall state
// looks like, it assumes `cart` is a root reducer/state property.
export const cartQuantitySelector = (state) => state.cart.products.reduce(
(quantity, item) => quantity + item.quantity,
0
);
export const cartTotalSelector = (state) => state.cart.products.reduce(
(total, item) => total + item.price * item.quantity,
0
);
Getting the cart quantity & cart total in component
import { useSelector } from 'react-redux';
import { cartQuantitySelector, cartTotalSelector } from '../path/to/CartRedux';
...
const cartQuantity = useSelector(cartQuantitySelector);
const cartTotal = useSelector(cartTotalSelector);
...