Angular:使用Immutable.js更新ngrx-store状态的嵌套数组

时间:2018-01-09 18:43:37

标签: angular typescript redux immutable.js ngrx-store


我试图上传我的一个目标的状态但目前没有成功。
每当用户点击Add To Cart时,我想用新项目更新购物车记录 这是我的ngrx-store州:

export interface UserState extends Map<string, any> {
    user: User;
    cart: Cart;
    addedToCart: boolean;
}

/* Initial state of any user */
export const UserStateRecord = Record( {
    user: Map( {} ),
    cart: Map( {} ),
    addedToCart: false
} );

购物车型号如下:

export class Cart {
    constructor(
        public created: string,
        public totalAmount: number,
        public items: List<Item>
    ) { }
}

export class Item {
    constructor(
        public quantity: number,
        public totalAmount: number,
        public product: Product
    ) {  }
}

当用户将项目添加到其购物车时,将调度ADD_TO_CART类型的操作。 如果物品已经在购物车内,我需要更新数量和总价格,否则我需要在购物车中添加新商品。
以下是我现在写的减速器开关盒:

case UserActions.ADD_TO_CART:
    const newItems = state.cart.items.map( item => {
        if ( item.product.id === payload.id ) {
            return Map( item ).merge( {
                'quantity': 1 + item.quantity,
                'totalAmount': item.totalAmount + ( item.totalAmount / item.quantity )
            } );
        } else {
            return item;
        }
    } );
    //CODE SHOULD BE ADDED HERE TO UPDATE THE STATE
    return state.merge( {
        addedToCart: true
    } ) as UserState;

Q1 newItems包含新的项目集,但我不知道如何将它们合并到州。你知道吗?

Q2 :另外,如果新商品尚未加入购物车,我该如何添加新商品?

Q3 :我必须将我的项目转换为地图(地图(项目))才能使用合并,但最好已经为购物车中的每个项目设置了地图。有人知道如何实现这个目标吗?

提前谢谢

1 个答案:

答案 0 :(得分:0)

您上面的示例有点令人困惑,因为您说您的模型是普通类,但在您的状态下它们显示为Map s ...

export const UserStateRecord = Record( {
    user: Map( {} ), // this disagrees with the User class!
    cart: Map( {} ), // this disagrees with the Cart class!
    addedToCart: false
} );

假设你真正的意思是用户和购物车类也RecordUserState那样继承Map方法......

使用updateupdateIn这样的事情应该可以解决减速器开关的问题......

return state.merge({
  // immutably update items in cart, providing default empty items List if not existing
  cart: state.cart.updateIn(
    ['items'], // path
    List<Item>(), // default empty item list iof not existing
    (items: List<Item>) => items.update( // updater for existing items
      // find index of exsisting item
      state.cart.items.findIndex(item => item.product.id === payload.id),
      // the new item to add if index not found, assuming this is in payload as not shown above 
      payload.item, 
      // updater for existing item, lets stay immutable and just create a new Item instance with updated properties
      existing => new Item(existing.quantity + 1, 
                          existing.totalAmount + (existing.totalAmount / existing.quantity), // not sure what this is calculating but you had it in original
                          existing.product)                 
    )
  ),
  addedToCart: true
})

然而,你对Records的定义似乎也不适合我,为了编译上面并强烈输入记录,而不是使用class Cart extends Map<string, any>我使用了以下技巧来扩展包含你的实例Record字段的默认值,并明确声明访问者的属性类型......

export class Cart extends Record({created: undefined, totalAmount: 0, items: List<Item>()}) {
  created: string
  totalAmount: number
  items: List<Item>
}

// omitting `user` as has no bearing on this question
export class UserState extends Record({cart: undefined, addedToCart: false}) {
  cart: Cart
  addedToCart: boolean
}

export const state = new UserState({cart: new Cart()})