当用户将同一产品添加到购物车中时,我试图在该状态下增加同一产品的对象属性quantity
,而不是在状态下创建具有相同属性的新对象。由于状态不应该直接突变,因此我将创建状态的副本,编辑quantity
,然后返回新数组。但是我得到"Error trying to diff '[object Object]'. Only arrays and iterables are allowed"
。这是正确的“ redux”方法吗?下面是我在根减速器中添加到购物车的情况。
export function rootReducer(state, action): IAppState {
switch(action.type) {
case ADD_PRODUCT:
return Object.assign({}, state, {
products: state.products.concat( Object.assign({}, action.payload) )
});
case REMOVE_PRODUCT:
return Object.assign({}, state, {
products: state.products.filter(t => t.id !== action.payload)
});
case REMOVE_ALL_PRODUCTS:
return Object.assign({}, state, {
products: []
});
case ADD_TO_CART:
let duplicateItem = state.cartProducts.filter(item => item.id === action.payload.id);
let duplicateIndex;
if(duplicateItem.length) {
for(var i = 0; i <= state.cartProducts.length - 1; i++){
if(state.cartProducts[i].id === duplicateItem[0].id){
duplicateIndex = i;
}
}
let newArray = {...state.cartProducts};
newArray[duplicateIndex].quantity = newArray[duplicateIndex].quantity === undefined ? 1 : newArray[duplicateIndex].quantity++;
return Object.assign({}, state, {
cartProducts: newArray
});
}
return Object.assign({}, state, {
cartProducts: state.cartProducts.concat( Object.assign({}, action.payload.product ) )
});
case REMOVE_FROM_CART:
return Object.assign({}, state, {
cartProducts: state.cartProducts.filter(t => t.id !== action.payload)
});
case CLEAR_CART:
return Object.assign({}, state, {
cartProducts: []
});
}
return state;
}
下面是接口
export interface IProduct {
id: string;
name: string;
price: string;
category: string;
quantity?: number;
}
export interface IAppState {
products: IProduct[];
cartProducts: IProduct[];
}
答案 0 :(得分:0)
您可能希望用新的数量修改cartProducts。 通过遍历cartproducts的简单循环即可解决问题。
case ADD_TO_CART :
return Object.assign({}, state, {
cartProducts: state.cartProducts.map((item, index) => (item.id === action.payload.id)
? item.quantity++ : item.quantity = 1)
})
答案 1 :(得分:0)
首先,当您使用spread operator
时,它只是为第一级创建新的引用。但是,第二级指向相同的参考。
例如,
let collection = [
{
someData: 1
}
]
let secondCollection = collection.map(item =>
item.someData = 2
)
console.log(collection) //[{someData: 2}]
console.log(secondCollection) //[{someData: 2}]
在这种情况下,您还必须复制第二级。使用Spread运算符,例如
let secondCollection = collection.map(item => {
let newItem = {
...item
}
newItem.someData: 2
return newItem
})
console.log(collection) //[{someData: 1}]
console.log(secondCollection) //[{someData: 2}]
这可能令人沮丧,并且有许多方法可以减轻麻烦。 Normalization
是一种好方法。这是redux状态的参考:
https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape
如果您愿意使用第三方库,则cloneDeep
中有lodash
种方法可以为您复制深层次:
https://lodash.com/docs/4.17.11#cloneDeep
对于您的更新购物车:
可以简化很多。绝对没有必要将重复项放入数组中,并且for
遍历整个循环。
让我们尝试简化它:
//assuming the carProducts state as
[
{
id: 1,
quantity: 2,
},
{
id: 2,
quantity: 2,
}
]
let newState = carProducts.map(item => {
let newItem = {...item} //or _.cloneDeep(item)
newItem.quantity = item.quantity + 1 //or add up the payload
return newItem
})
您还应该在不同的reducer中分离产品,carProducts等状态,以简化操作并增强控制力。
如果您有不清楚的地方,请随时发表评论:)