减速器:添加到数组数据

reducer: adding to array data

如果我从初始状态的外部来源提取一些数据,然后想要添加其他信息,例如 'liked'? 我已经尝试添加到产品数组,但它变得混乱,我想我应该为喜欢的项目添加一个额外的数组,然后将产品 ID 放入其中,唯一的事情是我需要它来反映它拥有的产品被点赞,我正在将产品数据映射到该项目。

解决此问题的最佳方法是什么?

const initialState = {
  isFetching: false,
  products: [],
};

我应该添加收藏夹吗:[] ?

当我将产品数组映射到产品组件时,如何将喜欢的状态反映到我的产品中?并且喜欢的状态现在在收藏中?

我尝试这样做以将其添加到产品数组中,但它变得非常混乱(像这样)

case ADD_LIKED:
 state.products[action.index]['liked'] = true;
 return state;
state.products[action.index]['liked'] = true;

这里的问题是你正在改变 reducer 内部的状态,它是 things you should never do inside a reducer.

之一

如果将函数分解成更小的部分,您会发现编写不改变数据的函数会容易得多。例如,您可以开始拆分您的应用程序。

function productsReducer(products = [], action) {
  // this reducer only deals with the products part of the state.
  switch(action) {
    case ADD_LIKED:
      // deal with the action
    default:
      return products;
  }
}

function app(state = {}, action) {
  return {
    isFetching: state.isFetching,
    products: productsReducer(state.products, action)
  }
}

在这种情况下,我肯定想写一个不变性小助手。

function replaceAtIndex(list, index, replacer) {
  const replacement = replacer(list[index]);

  const itemsBefore = list.slice(0, index),
        itemsAfter = list.slice(index + 1);

  return [...itemsBefore, replacement, ...itemsAfter];
}

您可以使用用于更改列表中对象的通用函数对其进行补充。

function updateInList(list, index, props) {
  return replaceAtIndex(list, index, item => {
    return { ...props, ...item };
  });
}

然后你可以用不可变的形式重写你的函数

 switch(action) {
    case ADD_LIKED:
      return updateInList(products, action.index, { liked: true });
    default:
      return products;
  }

您甚至可以通过部分应用该功能来获得乐趣。这允许您在 reducer 中编写非常有表现力的代码。

 const updateProduct = updateInList.bind(this, products, action.index);

 switch(action) {
    case ADD_LIKED:
      return updateProduct({ liked: true });
    case REMOVE_LIKED:
      return updateProduct({ liked: false });
    default:
      return products;
  }