当字段之一是数组时,如何更改状态对象?

时间:2018-09-29 22:32:10

标签: javascript reactjs redux

我有这种形式的状态树:

    const initialState = {
    total: 0,
    discount: 0,
    typeDiscount: 0,
    products: data
};

其中product字段是一个数组,而该数组是这样的:

[{
   "id":9090,
   "name":"Item1",
   "price":200,
   "discount":10,
   "type":"fiction",
   "quantity": 1,
   "img_url":"https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
},
{
   "id":9091,
   "name":"Item2",
   "price":250,
   "discount":15,
   "type":"literature",
   "quantity": 1,
   "img_url":"https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
}]

现在我正在尝试更改该数组中的数量,我是Redux的新手,所以请指导我如何执行此操作?

这是我的减速器:

case types.ADD_ITEM_CART:
        let product_add = state.products
        for (let i = 0; i < product_add.length; i++) {
            if (product_add[i].id === action.id) {
                product_add[i].quantity = product_add[i].quantity + 1
                break
            }
        }
        return dotProp.set(state, `products`, product_add);

3 个答案:

答案 0 :(得分:5)

您可以使用Array.prototype.map遍历项目,并从有效载荷中更新与id匹配的项目。

类似的东西:

const state = [{
    "id": 9090,
    "name": "Item1",
    "price": 200,
    "discount": 10,
    "type": "fiction",
    "quantity": 1,
    "img_url": "https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
  },
  {
    "id": 9091,
    "name": "Item2",
    "price": 250,
    "discount": 15,
    "type": "literature",
    "quantity": 1,
    "img_url": "https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
  }
];

const payload = {
  id: 9091
};

const nextState = state.map(product => {
  if (product.id !== payload.id) {
    // not our product, return as is
    return product;
  }
  return {
    ...product,
    quantity: product.quantity + 1
  }
});

console.log(nextState);
.as-console-wrapper {
  max-height: 100% !important;
}

要删除项目,您只需使用Array.prototype.filter

const state = [{
    "id": 9090,
    "name": "Item1",
    "price": 200,
    "discount": 10,
    "type": "fiction",
    "quantity": 1,
    "img_url": "https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
  },
  {
    "id": 9091,
    "name": "Item2",
    "price": 250,
    "discount": 15,
    "type": "literature",
    "quantity": 1,
    "img_url": "https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
  }
];

const payload = {
  id: 9091
};

const nextState = state.filter(product => product.id !== payload.id);

console.log(nextState);

答案 1 :(得分:2)

使用价差运算符...array.map(),您可以创建一个新产品数组,在为您创建新产品对象时,所有与ID不匹配的产品都将保留相同的对象引用感兴趣的产品:

case types.ADD_ITEM_CART:
    const updatedProducts = state.products.map(product => {
       if (product.id === action.id) {
            const newQuantity = product.quantity + 1;
            return { ...product, quantity: newQuantity };
        }

        return product;
    })

    return { ...state, products: updatedProducts };
}

编辑:使用array.filter()方法可以轻松实现删除,该方法将创建一个仅包含与谓词函数匹配的项目的新数组;在这种情况下,所有与您要删除的产品ID不匹配的产品:

 case types.REMOVE_ITEM_CART:
    const updatedProducts = state.products.filter(product => product.id !== action.id)

    return { ...state, products: updatedProducts };
}

答案 2 :(得分:2)

请勿像Redux或React本身那样改变您的状态。复制对象不会创建其他对象。如果您为新的属性更改属性,则也会对原始属性进行变异。

通常,我们使用Object.assign或扩展语法结合.map.filter之类的方法。 Object.assign或传播语法也不会创建完全不同的对象。他们创建浅拷贝,这意味着一层拷贝。如果您为新对象更改了嵌套属性,则再次更改原始对象。因此,请结合所有这些工具。

case types.ADD_ITEM_CART: {
    // We are mapping our related array.
    const newProducts = state.products.map( el => {
      // If id does not match, return the element without doing nothing.
      if ( el.id !== action.id ) { return el };
      // id match, increment the quantity.
      return { ...el, quantity: el.quantity + 1 };
    })
    // Lastly, return our state again without mutating it.
    return { ...state, products: newProducts };
}

如果要从数组中删除项目,通常为此使用.filter方法。

const newProducts = state.products.filter( el => el.id !== action.id );
return { ...state, products: newProducts };