我有几个级别嵌套的项目:
const initialState = {
sections: [
{
name: 'Section 1',
categories: [
{
name: 'Category 1',
checklist: [
{ name: 'Item 1', checked: false },
{ name: 'Item 2', checked: true },
{ name: 'Item 3', checked: false },
]
},
// more categories
],
},
// more sections
],
};
我想知道是否有办法改变他们的状态(例如,切换checked
属性)而不显式传递大量上下文:
function toggleCheckbox(sectionId, categoryId, itemId) {
return {
type: 'TOGGLE_CHECKBOX',
sectionId: sectionId,
categoryId: categoryId,
itemId: itemId,
};
}
function reducer(state = initialState, action) {
switch (action.type) {
case 'TOGGLE_CHECKBOX':
return Object.assign({}, state, {
sections: state.sections.map(function (section, i) {
return i === action.sectionId ? Object.assign({}, section, {
categories: section.categories.map(function (category, j) {
return j === action.categoryId ? Object.assign({}, category, {
checklist: category.checklist.map(function (item, k) {
return k === action.itemId ? Object.assign({}, item, {
checked: !item.checked,
}) : item;
}),
}) : category;
}),
}) : section;
}),
});
default:
return state;
}
}
随着部分,类别和清单的逻辑增长,我可能希望将它们作为单独的Reducer提取,但因为它们是嵌套的,所以我没有看到这样做的方法。
这里有一个bin,这个商店用React可视化。
我想我的问题有两部分:
答案 0 :(得分:2)
嵌套对象肯定会很痛苦。 Dan对Redux docs中的嵌套实体有一点了解。
如果您有嵌套实体,或者您允许用户编辑收到 实体,你应该将它们分开保存在状态中,好像它是一个 数据库。在分页信息中,您只能通过它们来引用它们 他们的身份证这使您可以始终保持最新状态。
我已经修改了你的示例 jsbin 来进行演示,但它的要点包括将状态树稍微扁平一点。
const initialState = {
sections: [
{
name: 'Section 1',
categories: [ 'Category 1'],
},
// more sections
],
categories: [
{
name: 'Category 1',
checklist: ['Item 1', 'Item 2', 'Item 3']
},
],
items: [
{
name: 'Item 1',
checked: false
},
{
name: 'Item 2',
checked: true
},
{
name: 'Item 3',
checked: false
},
]
};
项目缩减器现在需要name
才能知道要更新哪一个,而各个部分/类别会跟踪他们拥有哪些项目。现在,您可以拆分专用的类别,部分和项目缩减器,每个都可以处理他们自己关注的领域!
如果你想要在不同类别中使用相同名称的项目,你必须引入一个新ID以使它们彼此分开......但是现在使用名称是最简单的 < / p>