So, I don't know if how I want this to work is possible at all, but in my head I think it could I just can't seem to get it to work..
Basically I have an empty array of objects:
this.state = {
orders: [{}]
}
Then when I click on a button I want an order to be added (custom event because cart has no parent-child relations to the button clicked, for reasons):
pubSub.on("addToCart", (data) =>
this.setState((prevState => ({
orders: [...prevState.orders, data.order]
})
);
This works. I end up with:
orders: [
{[sku]: sku, quantity: quantity}
]
Now the problem I am stuck with is that if an order is to be added with an SKU that is already in the array, I want just the quantity to be updated. If the SKU isn't already found in the array, I want a new order added. So I want to check the array for the existence of a key (key SKU is the same as the value of key SKU).
So, to check an array for the existence of a key I would use:
this.state.orders.map(obj =>{
if (!(data.sku in obj)){
**setState here with order added**
}
})
I know how the conditional should look like if it finds that the key exists, and then only update the quantity.
the problem I face is that it iterates over all the orders in the array, and every time the key doesn't exist, it adds a new order. How could I make this, so it checks for the existence of a key, and only adds a new order 1 time if that's the case, and not every time? I want actually to first check all the keys, and then decide what to do. With this approach, I have to decide every round of the map what should be done.
Also keep in mind that we are in the scope of a custom event handler, where I want to use data. inside this handler, I cannot assign variables outside the scope of the map function. So basically it's or I use just setState, or I use the map function and inside there the setState. I can't use them both next to each other as data is only available in the first method call. This is also the first time I try to use this custom event handler thing, and the scoping has tied my hands a bit.
If this makes sense, and someone can point me in the right direction, that would be greatly appreciated. Thanks in advance!
You can pass function in setState
. This function will have current state and, if you use classes, current props. In this function you create state change
- part of state object that you want to update. In your case it might look like this (it's barebones and dirty, to show how you can do it):
// data is here, somwhere
this.setState(function(state, props) {
let index = state.orders.findIndex(obj => data.sku in obj);
if (index > -1) {
// update existing
return {orders: state.orders.slice(0, index).concat(
{...state.orders[index], quantity: state.orders[index].quantitiy + 1},
state.orders.slice(index+1))}
} else {
// create new
return {orders: state.orders.concat(data)}
}
})