通过单击按钮来响应、有条件的 setState

React, conditional setState with the click of a button

所以,我完全不知道我希望它如何工作是可能的,但在我的脑海里我认为它可能只是我似乎无法让它工作..

基本上我有一个空对象数组:

this.state = {
     orders: [{}]
}

然后当我点击一个按钮时我想添加一个订单(自定义事件因为购物车与点击的按钮没有父子关系,原因):

pubSub.on("addToCart", (data) =>
   this.setState((prevState => ({
      orders: [...prevState.orders, data.order]
   })
);

这行得通。我最终得到:

orders: [
 {[sku]: sku, quantity: quantity}
]

现在我遇到的问题是,如果要使用数组中已有的 SKU 添加订单,我只想更新数量。 如果尚未在数组中找到 SKU,我想添加一个新订单。 所以我想检查数组是否存在一个键(键SKU与键SKU的值相同)。

因此,要检查数组中是否存在密钥,我会使用:

this.state.orders.map(obj =>{
  if (!(data.sku in obj)){
    **setState here with order added**
  }
})

我知道如果发现键存在,条件应该是什么样子,然后只更新数量。

我遇到的问题是它遍历数组中的所有订单,每次键不存在时,它都会添加一个新订单。 我该怎么做,所以它会检查密钥是否存在,如果是这样的话,只添加一个新订单 1 次,而不是每次都这样? 我实际上想先检查所有的键,然后再决定要做什么。 使用这种方法,我必须决定每一轮地图应该做什么。

还要记住,我们处于自定义事件处理程序的范围内,我想在其中使用 data。 在这个处理程序中,我不能在 map 函数的范围之外分配变量。所以基本上是,或者我只使用 setState,或者我使用 map 函数并在其中使用 setState。我不能同时使用它们,因为数据仅在第一个方法调用中可用。 这也是我第一次尝试使用这个自定义事件处理程序,范围界定让我有点束手无策。

如果这是有道理的,并且有人可以指出正确的方向,那将不胜感激。 提前致谢!

您可以在 setState 中传递函数。此函数将具有当前状态,如果您使用 类,则当前道具。在此函数中,您创建 state change - 您要更新的状态对象的一部分。在你的情况下,它可能看起来像这样(它是准系统和肮脏的,以展示你如何做到这一点):

// 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)}
  }
})