Angular / Redux正确保持状态的方法

时间:2017-11-23 17:27:47

标签: javascript angular redux observable shopping-cart

我正在使用 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 并将其用于另一个添加的对象数组?因此,为购物车产品和标记添加产品提供两个不同的阵列,我将相应地保留添加的对象及其状态?

1 个答案:

答案 0 :(得分:1)

首先,我不会将此逻辑添加到您的rootReducerRemember, 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的工作是简单地定义状态如何变化,而不是定义状态是什么。在您的行动或中间件中执行此操作。

我也倾向于通过你的州通过整个行动,而不是只有一把钥匙。这样,如果你需要在你的州进一步采取行动的另一部分,你就不必重构。