我正在使用 Angular + Redux 构建购物车应用。 我有一系列对象(我的购物车中产品),每个界面都有:
export interface IProduct {
id: number;
description: string;
isAdded: boolean;
}
页面中的产品有一个按钮添加到购物车
<div class="addBtn" (click)="addToCart(prod)">
<span class="unaddedItem" *ngIf="!prod.isAdded; else added">Add to cart</span>
<ng-template>
<span class="addedItem" #added>In cart</span>
</ng-template>
</div>
我想要的是在添加产品时使用在购物车中更改添加到购物车文本。我使用 Rxjs 成功完成了这项工作,但是当我离开产品页面然后返回到该页面时,我的购物车范围内的已添加产品丢失(添加到购物车再次显示)。所以,我认为 Redux 是帮助我保持状态的唯一方法。
我用一些动作写了一个reducer函数。这是其中之一:
export function rootReducer(state, action){
switch(action.type){
case ADD_PRODUCT:
action.product.id = state.products.length + 1;
return Object.assign({}, state, {
products: state.products.concat(Object.assign({}, action.product))
})
}
}
所以,我的问题在购物车中添加对象后保持对象状态的正确方法是什么? 我应该使用相同的 ADD_PRODUCT 操作,还是应该编写另一个操作,例如 MARK_ADDED 并将其用于另一个添加的对象数组?因此,为购物车产品和标记添加产品提供两个不同的阵列,我将相应地保留添加的对象及其状态?
答案 0 :(得分:1)
首先,我不会将此逻辑添加到您的rootReducer
。 Remember, your reducers mimic the shape of your data。状态应该从您的rootReducer流向各个状态切片。在下面的示例中,您理想地需要一个返回整个状态的rootReducer。产品和购物车减速器,返回by_id和all_ids等,直到构建整个数据结构。
对于您的购物车和产品,我更倾向于遵循以下方面:
{
products: {
by_id: {
1: {
id: 1,
name: "hairdryer",
price: "2.99",
in_cart: true
},
2: {
id: 2,
name: "brush",
price: "299.99",
in_cart: false
}
},
all_ids: [1, 2]
},
cart: {
products_added: [1],
saved: false,
some_data: "foo"
}
}
这遵循doc示例中列出的结构。当调度add_to_cart
动作时,其对象将通过每个减速器向下传递,产品将看到此数据以及购物车。如文档中所示,我只在产品中的in_cart
减速器和购物车中的products_added
减速器中使用switch语句。
在减速机中添加UUID分配也是不好的做法。 reducer的工作是简单地定义状态如何变化,而不是定义状态是什么。在您的行动或中间件中执行此操作。
我也倾向于通过你的州通过整个行动,而不是只有一把钥匙。这样,如果你需要在你的州进一步采取行动的另一部分,你就不必重构。