Reactjs 如何在不显式提供大量操作上下文的情况下更改深度嵌套的状态?

Reactjs 如何在不显式提供大量操作上下文的情况下更改深度嵌套的状态?,reactjs,redux,Reactjs,Redux,我将项目嵌套在两个层次上: const initialState = { sections: [ { name: 'Section 1', categories: [ { name: 'Category 1', checklist: [ { name: 'Item 1', checked: false }, { name: 'Item 2', checked

我将项目嵌套在两个层次上:

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;
  }
}
随着节、类别和检查表逻辑的增长,我可能希望将它们提取为单独的缩减器,但因为它们是嵌套的,所以我看不到实现这一点的方法

这是一个用React可视化的商店

我想我的问题有两部分:

  • 如何将它们作为单独的还原剂提取
  • 我如何避免显式地提供这么多上下文,并避免所有实际上只更改嵌套项状态的映射

  • 嵌套对象肯定会很痛苦。Dan在中的嵌套实体上有一点模糊

    如果您有嵌套实体,或者您允许用户编辑 实体,您应该将它们单独保存在状态中,就像它是一个 数据库在分页信息中,您只能通过 他们的身份证。这使您能够始终使它们保持最新

    我对您的示例进行了修改,以进行演示,但其要点包括稍微展平您的状态树

    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
        },
      ]
    
    })

    条目缩减器现在只需要一个
    名称
    ,就可以知道要更新哪个条目,而区段/类别则可以跟踪它们所拥有的条目。现在,您可以拆分专门的类别、部分和项目缩减器,它们可以分别处理各自关注的领域


    如果您希望在不同类别中使用相同名称的项目,则必须引入新ID以使它们彼此分开。。。但现在使用名称是最简单的

    这是一个非常好的答案。只有一个问题,在我的例子中,我有多个部分都有相同的类别,但每个类别都有不同的检查表。然后我是否将这些重复的类别视为不同的类别,并为它们提供所有不同的ID?因此,如果我有3个部分,每个部分有3个类别,我在
    categories
    字段中总共有9个类别?嗯。我认为这取决于您的使用情况,但很可能您总共需要9个类别,因为每个类别需要不同的检查表。如果您试图在所有部分中共享这3个类别,您的类别将需要为每个部分分别列出
    项目
    列表。也许更直截了当地给出每个部分自己独特的类别,即使它们的名称相同。