Redux - 从规范化状态树添加/删除项目

时间:2017-11-19 10:27:36

标签: redux react-redux

我已经规范了我正在处理的应用的状态(基于this article)并且我试图添加/删除部分状态树中的项目基于数量。

我的州树cart的一部分全权负责存放购物车中的门票数量,按ID排列。当用户更改数量时,系统会调度UPDATE_QTY,其中包含qtyid

状态开始正确,因为传入的数据包含qty但我似乎无法找出从cart缩减器移除项目的语法qty0,如果qty为1或更多,也会重新添加。

有人可以就正确的语法提供建议吗?

编辑:我想知道我是否在UPDATE_QTY操作中尝试做太多操作,并且我应该有单独的操作来删除和添加项目。

byId reducer

export function byId(state = initialState, action) {
  switch (action.type) {
    case SET_INITIAL_CART_DATA:
      return Object.assign({}, state, action.tickets);

    case UPDATE_QTY: // Here, I need to check if action.qty is 0 and if it is I need to remove the item but also add it back in if action.qty > 0
      return {
        ...state,
        [action.id]: { ...state[action.id], qty: action.qty }, // Updating the qty here works fine
      };
    default:
      return state;
  }
}

Simplfied状态树

const state = {
  cart: {
    byId: {
      '40': { // How can I remove these items when qty is 0 or add back in if > 0?
        qty: 0,
        id: '40'
      },
      '90': {
        qty: 0,
        id: '90'
      }
    },
    allIds: [
      [
        '40',
        '90',
      ]
    ]
  },
}

我还需要在我的allIds缩减器中反映ID。

allIds reducer

export function allIds(state = [], action) {
  switch (action.type) {
    case SET_INITIAL_CART_DATA:
      return [...state, ...action.allIds];

    case UPDATE_QTY:
        return [ONLY IDS WITH QTY]
    default:
      return state;
  }
}

为此,我不确定allIds减速器是否需要连接到byIds减速器并从那里获取信息。我很想知道这样的事情的最佳实践。

2 个答案:

答案 0 :(得分:0)

为什么byIdsallIds有单独的缩减器?我会将这些合并到一个cart缩减器中,并将allIds状态保持为byIds

case SET_INITIAL_CART_DATA:
  // just guessing here...
  const { tickets } = action;
  const allIds = tickets
    .reduce((arr, ticket) => arr.concat(ticket.id), []);

  return {
    byIds: { ...tickets },
    allIds
  }

case UPDATE_QTY: {
  const { byIds, allIds } = state;
  const { id, qty } = action;
  const idx = allIds.indexOf(id);
  const next = { };

  if (qty > 0) {
    next.byIds = {
      ...byIds,
      [id]: { id, qty }
    };
    next.allIds = idx === -1 ? allIds.concat(id) : [ ...allIds ];
    return next;
  }

  next.byIds = { ...byIds };
  delete next.byIds[id];

  next.allIds = idx === -1 ? [ ...allIds ] : [
    ...allIds.slice(0, idx),
    ...allIds.slice(idx + 1)
  ];

  return next;
}

但是,你想要哪种状态归一化?如果这代表购物车的购物车,那么门票将被标准化,并且购物车将仅代表要购买的门票的数量。然后你的州看起来像这样:

{
  tickets: {
    byIds: {
      '1': { id, name, price, ... },
      '2': { ... },
      '3': { ... },
      ...
    }
    allIds: [ '1', '2', '3', ... ]
  },
  cart: [
    { id: 2, qty: 2 },
    { id: 1, qty: 1 }
  ]
}

使用数组作为购物车状态可以维持广告订单。

答案 1 :(得分:0)

有时候(当您仅遍历id并通过id获取时)足以从allId中删除id并跳过所有不必要的计算。

    case actionTypes.DELETE_ITEM: {
        const filteredIds = state.allIds.filter(id => id !== action.itemId);
        return {
            ...state,
            allIds: filteredIds
        };
    }