【问题标题】:What is the problem in this redux action and reducer?这个 redux action 和 reducer 有什么问题?
【发布时间】:2020-01-16 15:58:28
【问题描述】:

我知道一旦该组件的状态发生更改,redux 会触发响应组件重新渲染,但在我的情况下不会发生这种情况。

动作

const addToCart = (product, cartProducts) => {
   let newCartProducts = [...cartProducts, product];

   newCartProducts = newCartProducts.reduce((acc, cur) => {
      let repeated = acc.find(p => p.id === cur.id);
      if(repeated)  repeated.quantity++;   
      else acc.push(cur);
      return acc;
    }, []);

    return {
      type: ADD_TO_CART,
      payload: newCartProducts
    }
}

减速器

export default (state = [], action) => {
    switch (action.type) {
        case ADD_TO_CART:
            return action.payload;
        default:
            return state;
    }

}

每次从组件派发action时reducer都会返回一个新的状态但是我需要关闭购物车再打开才能达到效果,redux不会同时更新产品数量??

【问题讨论】:

  • 最好将不将现有产品添加到卡中的逻辑放在reducer中,例如if(state.map(cardItem=>cardItem.id).includes(action.payload.newItem)),如果redux开发工具说在调度操作后添加了项目,那么你的问题可能在卡片物品的容器中。
  • 是的,控制台一切正常?但是在我关闭并重新打开购物车之前,购物车产品数量不会更新......而且我认为该操作是放置我的逻辑并使减速器只返回数据的更好地方??
  • 您可以使用 React 开发工具查看组件接收到的属性,我怀疑容器或减速器中有问题,您没有发布它会改变包含购物车项目的对象而不是复制对象。

标签: javascript reactjs redux


【解决方案1】:

您正在修改状态中的现有元素。

使用

newCartProducts = newCartProducts.reduce((acc, cur) => {
  let repeatedIndex = acc.findIndex(p => p.id === cur.id);
  const repeated = acc[repeatedIndex];
  if (repeated) {
    acc[repeatedIndex] = { 
      ...repeated,
      quantity: repeated.quantity + 1
    };
  } else acc.push(cur);
  return acc;
}, []);

您的数组每次都会重新创建,但其中的对象不会。因此,当您修改它们的内部时,您需要通知特定对象已更改。

【讨论】:

  • 有一个更简单的方法来检查是否有双打,它应该在减速器而不是动作中完成。例如:state.map(p => p.id).includes(newProduct.id)。我没有看到 OP 在发布的代码中对某些内容进行了变异,redux 开发工具很棘手,因为它会在变异的更改上显示差异。
  • @HMR OP 想要一组独特的产品,但更新了 quantity 属性。
  • 但我同意有一种更简单的方法,而不是一直为所有购物车这样做。只需检查购物车,如果没有找到添加新产品,或者如果找到更新需要更新的产品。
  • 是的,这就是问题所在。嵌套对象有点棘手,因为您必须一直解构到要修改的属性:/
  • @CodeEagle 更新了我的答案,抱歉,我忽略了您设置的数量。假设这是删除双打的复杂方法。
【解决方案2】:

将逻辑重构为reducer并在此处设置数量:

const addToCart = product => {
  return {
    type: ADD_TO_CART,
    payload: product,
  };
};
//I assume state is an array of products on your cart
export default (state = [], action) => {
  switch (action.type) {
    case ADD_TO_CART:
      const { id } = action.payload;
      return state.map(p => p.id).includes(id)
        ? //product is already on card add quanity
          state.map(p =>
            p.id === id
              ? { ...p, quantity: p.quantity + 1 }
              : p
          )
        : state.concat({ ...action.payload, quantity: 1 }); // add product
    default:
      return state;
  }
};

【讨论】:

    猜你喜欢
    • 2019-06-20
    • 1970-01-01
    • 2018-01-13
    • 2019-05-16
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    相关资源
    最近更新 更多