Angular / Redux 保持状态的正确方式
Angular / Redux correct way to keep the state
我正在使用 Angular + Redux 构建一个购物车应用程序。
我有一个对象数组(Products 在我的购物车中),每个接口:
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>
我想要的是在添加产品时将 Add to cart 文本更改为 In cart。我用 Rxjs 成功地做到了,但是当我离开 Products 页面然后返回它时,我的 In cart 添加产品的跨度丢失(添加到购物车 再次显示)。所以,我认为 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 并使用它对于另一个添加的对象数组?因此,In cart products 和 Marked added products 有两个不同的数组,我将在其中相应地保留添加的对象及其状态?
首先,我不会将那个逻辑添加到您的 rootReducer
中。 Remember, your reducers mimic the shape of your data。状态应该从您的 rootReducer 流向各个状态片。在下面的示例中,理想情况下,您需要一个 returns 整个状态的 rootReducer。 returns 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"
}
}
这遵循文档示例中列出的结构。当一个 add_to_cart
动作被调度时,它的对象通过每个 reducer 向下传递,产品将看到这个数据以及购物车。如文档中所示,我只是在产品中的 in_cart
reducer 和购物车中的 products_added
reducer 中使用 switch 语句。
此外,在减速器中添加 UUID 分配也是一种不好的做法。 reducer 的工作是简单地定义状态如何变化,而不是定义状态是什么。在您的操作或中间件中执行此操作。
我也倾向于通过您的状态传递整个动作,而不是只传递一个键。这样,如果您需要在您的状态下进一步执行操作的另一部分,则无需重构。
我正在使用 Angular + Redux 构建一个购物车应用程序。 我有一个对象数组(Products 在我的购物车中),每个接口:
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>
我想要的是在添加产品时将 Add to cart 文本更改为 In cart。我用 Rxjs 成功地做到了,但是当我离开 Products 页面然后返回它时,我的 In cart 添加产品的跨度丢失(添加到购物车 再次显示)。所以,我认为 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 并使用它对于另一个添加的对象数组?因此,In cart products 和 Marked added products 有两个不同的数组,我将在其中相应地保留添加的对象及其状态?
首先,我不会将那个逻辑添加到您的 rootReducer
中。 Remember, your reducers mimic the shape of your data。状态应该从您的 rootReducer 流向各个状态片。在下面的示例中,理想情况下,您需要一个 returns 整个状态的 rootReducer。 returns 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"
}
}
这遵循文档示例中列出的结构。当一个 add_to_cart
动作被调度时,它的对象通过每个 reducer 向下传递,产品将看到这个数据以及购物车。如文档中所示,我只是在产品中的 in_cart
reducer 和购物车中的 products_added
reducer 中使用 switch 语句。
此外,在减速器中添加 UUID 分配也是一种不好的做法。 reducer 的工作是简单地定义状态如何变化,而不是定义状态是什么。在您的操作或中间件中执行此操作。
我也倾向于通过您的状态传递整个动作,而不是只传递一个键。这样,如果您需要在您的状态下进一步执行操作的另一部分,则无需重构。