So, I am making this shopping cart in redux-toolkit, where user can't order more than the quantity available. So, my reducer function is like below for adding to cart.
import { createSlice } from "@reduxjs/toolkit";
import { FoodCartType } from "../../types";
type CartState = {
cart: FoodCartType[];
};
const initialState: CartState = {
cart: [],
};
export const foodcartSlice = createSlice({
name: "foodcart",
initialState,
reducers: {
addToCart: (state, action) => {
console.log(action);
if (state.cart.length === 0) {
state.cart.push(action.payload);
}
const itemIndex = state.cart.findIndex(
(item) => item.id === action.payload.id
);
if (itemIndex >= 0) {
return {
...state,
cart: state.cart.map((item) => {
if (item.id === action.payload.id) {
return {
...item,
quantity: item.quantity 1,
quantity_available: item.quantity_available - 1,
};
}
}),
};
} else {
return {
...state,
cart: [
...state.cart,
{
...action.payload.product,
quantity: 1,
quantity_available: action.payload.quantity_available - 1,
},
],
};
}
},
},
});
export const { addToCart } = foodcartSlice.actions;
export default foodcartSlice.reducer;
When I click on the dispatch, on the component. I get the following error.
Unhandled Runtime Error Error: [Immer] An immer producer returned a new value and modified its draft. Either return a new value or modify the draft.
So, where I am doing the problem? if I just remove the itemIndex check part, items get pushed into the cart. But, other than that it is giving me this error. How should I rewrite this?
CodePudding user response:
Because your state.cart.push(action.payload);
line modifies the value of state
and later you return
a new value.
You are allowed to do one, but not both at once. See writing reducers with immer
What you could do here: always modify. That's also far more readable.
export const foodcartSlice = createSlice({
name: "foodcart",
initialState,
reducers: {
addToCart: (state, action) => {
console.log(action);
// you push later anyways, so you can also delete these lines
// if (state.cart.length === 0) {
// state.cart.push(action.payload);
// }
const itemIndex = state.cart.findIndex(
(item) => item.id === action.payload.id
);
if (itemIndex >= 0) {
state.cart[itemIndex].quantity = 1
state.cart[itemIndex].quantity_available -= 1
} else {
state.cart.push({
...action.payload.product,
quantity: 1,
quantity_available: action.payload.quantity_available - 1,
})
}
},
},
});