Reactjs can';即使在不改变对象和数组的情况下,也不能改变缩减器中的嵌套对象

Reactjs can';即使在不改变对象和数组的情况下,也不能改变缩减器中的嵌套对象,reactjs,ecmascript-6,redux,react-redux,Reactjs,Ecmascript 6,Redux,React Redux,我试图更新减速器中的状态,我知道我不应该改变对象或嵌套对象,所以我对数组使用map,对对象使用对象排列。但我似乎无法真正更改嵌套很深的值 除了我不能改变状态这一事实之外,我真的很不喜欢代码的外观,尤其是我只需要改变一个属性所需要的循环数。我觉得有一种更好、更具可读性、更高效的方法可以做到这一点 这是国家: const items = [{ name: 'item 1', id: 'item1', tags: [{ id: 'tag1', name: 'tag 1'

我试图更新减速器中的状态,我知道我不应该改变对象或嵌套对象,所以我对数组使用
map
,对对象使用对象排列。但我似乎无法真正更改嵌套很深的值

除了我不能改变状态这一事实之外,我真的很不喜欢代码的外观,尤其是我只需要改变一个属性所需要的循环数。我觉得有一种更好、更具可读性、更高效的方法可以做到这一点

这是国家:

const items = [{
  name: 'item 1',
  id: 'item1',
  tags: [{
    id: 'tag1',
    name: 'tag 1'
  }, {
    id: 'tag2',
    name: 'tag 2'
  }]
}, {
  name: 'item 2',
  id: 'item2',
  tags: [{
    id: 'tag1',
    name: 'tag 1'
  }, {
    id: 'tag4',
    name: 'tag 4'
  }]
}];
这是我正在发送的操作:

const action = {
  type: 'CHANGE_TAG_NAME',
  payload: {
    itemId: 'item2',
    tagId: 'tag4',
    newTagName: 'tag 44444'
  }
};
这是减速器:

const itemsReducer = (state = [], action) => {
  switch (action.type) {
    case 'CHANGE_TAG_NAME':
      {
        const itemIndex = state.findIndex(item => item.id === action.payload.itemId);
        const tagIndex = state[itemIndex].tags.findIndex(t => t.id === action.payload.tagId);
        const nextTag = {
          ...state[itemIndex].tags[tagIndex],
            name: action.payload.newTagName
        };
        const nextTags = [
          ...state[itemIndex].tags.slice(0, tagIndex),
          nextTag,
          ...state[itemIndex].tags.slice(tagIndex + 1, ),
        ];
        const nextItem = {
          ...state[itemIndex],
            tags: nextTags
        };

        const nextState = [
          ...state.slice(0, itemIndex),
          nextItem,
          ...state.slice(itemIndex + 1)
        ];
      }
    default:
      return state;
  }
};

您忘记了关键字
return

    //.....
    const nextState = [
      ...state.slice(0, itemIndex),
      nextItem,
      ...state.slice(itemIndex + 1)
    ];
    // HERE RETURN Your reducer should work just fine, you just forgot to return 
nextState
in your case block.

As for less iterations i suggests this pattern:
map over the items, if the current item's id is different from the
itemId
you have in the payload then return it as is.
If the item's id is the same then return a new object and then map over the tags, doing the same condition like you did with the item.
If the tag's id isn't the same as the
tagId
in the payload return it as is, if it does the same return a new object.

Here is a running example:

const items = [{
  name: 'item 1',
  id: 'item1',
  tags: [{
    id: 'tag1',
    name: 'tag 1'
  }, {
    id: 'tag2',
    name: 'tag 2'
  }]
}, {
  name: 'item 2',
  id: 'item2',
  tags: [{
    id: 'tag1',
    name: 'tag 1'
  }, {
    id: 'tag4',
    name: 'tag 4'
  }]
}];

const action = {
  type: 'CHANGE_TAG_NAME',
  payload: {
    itemId: 'item2',
    tagId: 'tag4',
    newTagName: 'tag 44444'
  }
};

const itemsReducer = (state = [], action) => {
  switch (action.type) {
    case 'CHANGE_TAG_NAME':
      {
        const {
          payload: {
            itemId,
            tagId,
            newTagName
          }
        } = action;
        const nextState = state.map(item => {
          if (item.id !== itemId) return item;
          return {
            ...item,
            tags: item.tags.map(tag => {
              if (tag.id !== tagId) return tag;
              return {
                ...tag,
                name: newTagName
              }
            })
          }
        });
        return nextState;
      }
    default:
      return state;
  }
};

console.log(itemsReducer(items, action));
/。。。。。
常数nextState=[
…state.slice(0,itemIndex),
nextItem,
…state.slice(itemIndex+1)
];

//这里RETURN您的减速机应该可以正常工作,您只是忘记了在case块中返回
nextState

对于较少的迭代,我建议使用这种模式:
映射项目,如果当前项目的id与有效负载中的
itemId
不同,则按原样返回。
如果项目的id相同,则返回一个新对象,然后映射到标记上,执行与项目相同的条件。
如果标签的id与有效负载中的
tagId
不同,则按原样返回,如果相同,则返回新对象

下面是一个运行示例:

const项=[{
名称:“项目1”,
id:'item1',
标签:[{
id:'tag1',
名称:“标记1”
}, {
id:'tag2',
名称:“标签2”
}]
}, {
名称:“项目2”,
id:'项目2',
标签:[{
id:'tag1',
名称:“标记1”
}, {
id:'tag4',
名称:“标签4”
}]
}];
常量动作={
键入:“更改标签名称”,
有效载荷:{
itemId:'item2',
tagId:'tag4',
新标签名:“标签44444”
}
};
const itemsReducer=(state=[],action)=>{
开关(动作类型){
案例“更改标签名称”:
{
常数{
有效载荷:{
itemId,
塔吉德,
新大名
}
}=行动;
const nextState=state.map(项=>{
如果(item.id!==itemId)返回项目;
返回{
…项目,
标记:item.tags.map(标记=>{
如果(tag.id!==tagId)返回标签;
返回{
…标签,
姓名:newTagName
}
})
}
});
返回下一状态;
}
违约:
返回状态;
}
};

日志(itemsReducer(items,action))这是一个很好的模式,谢谢。我应该多研究一下