Hey everyone I am trying to find the best way to update a property value of an object inside an array of objects, without mutating the array, inside my reducer.
Here is my reducer file :
const initialState = {
products:[]
};
export default function basketReducer(state = initialState, action){
switch (action.type) {
case "ADD_PRODUCT_TO_BASKET":
return state
case "REMOVE_PRODUCT_FROM_BASKET":
return state
default:
return state
}
};
Here is an example of a product object :
{
id: 1,
name: "product 1",
quantity: 1,
price: 1.0,
}
When I add a product that is already in my array (same id), I want to increment his quantity property by one. I already have the function to check if the item already exists in my array, I am just searching for a way to update the quantity property without mutating the array.
Thanks for the help!
UPDATE : According to the answer of @Will Jenkins i wrote this code :
case "ADD_PRODUCT_TO_BASKET": {
const index = state.products.findIndex(p => p.id === action.payload.id);
if(index !== -1){
const productId = action.payload.id
return {...state, products: state.products.map(p => p.id === productId ? {...p, quantity:p.quantity+1} : p)}
}else {
return {products: [...state.products].concat(action.payload)};
}
}
This is working well, when I add a new product there is appended to the array and if I add the same product his quantity is incremented by one, but I am pretty sure I can refactor this code, does anyone have a proposition?
Assuming you're passing the product id as the payload of your action, map over your products and increment the quantity of the one that matches the id:
case "ADD_PRODUCT_TO_BASKET": {
const productId = payload
return {...state, products: state.products.map(p => p.id === productId ? {...p, quantity:p.quantity+1} : p)}
}
Update
I'd go for something a bit more long-form so it's easier for others (or future you) to understand and maintain:
case "ADD_PRODUCT_TO_BASKET": {
const addedProduct = action.payload;
const productId = addedProduct.id;
const exists = state.products.some((p) => p.id === productId);
if (exists) {
const products = state.products.map((p) =>
p.id === productId ? { ...p, quantity: p.quantity + 1 } : p
);
return { ...state, products };
} else {
return {
...state,
products: [...state.products, { ...addedProduct }]
};
}
}