减速器:添加到数组数据
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;
}
如果我从初始状态的外部来源提取一些数据,然后想要添加其他信息,例如 '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;
}