Angular 为什么它被认为是NgRx中存储值的直接修改

Angular 为什么它被认为是NgRx中存储值的直接修改,angular,ngrx,ngrx-store,Angular,Ngrx,Ngrx Store,关于代码片段的信息:state有一个切片educationList,它是各种教育(学士、硕士、博士)的数组。educationList数组中的每个项目都包含另一个数组description,其中包含项目、论文等的信息 以下是用于删除description数组中某个项的代码段: case Actions.DELETE_ROLE: { let updatedEducationList = [...state.educationList]; const targetIndex

关于代码片段的信息:state有一个切片
educationList
,它是各种教育(学士、硕士、博士)的数组。
educationList
数组中的每个项目都包含另一个数组
description
,其中包含项目、论文等的信息

以下是用于删除
description
数组中某个项的代码段:

case Actions.DELETE_ROLE: {
      let updatedEducationList = [...state.educationList];
      const targetIndex = updatedEducationList.findIndex((educationItem) => {
        return educationItem.id === action.payload.educationId;
      });
      let oldDescription = updatedEducationList[targetIndex].description;
      let newDescription = oldDescription.filter((item, index) => index !== action.payload.roleIndex);
      updatedEducationList[targetIndex] = { ...updatedEducationList[targetIndex], description: newDescription };
      return { ...state, educationList: updatedEducationList };
    }
如果代码段中有以下行

updatedEducationList[targetIndex] = { ...updatedEducationList[targetIndex], description: newDescription }
被替换为

updatedEducationList[targetIndex].description = newDescription;  //Edited this line
发生错误。错误如下

core.js:6014 ERROR TypeError: Cannot assign to read only property 'description' of object '[object Object]'
    at educationListReducer (education-list.reducer.ts:110)
    at combination (store.js:303)
    at store.js:1213
    at store.js:383
    at ScanSubscriber.reduceState [as accumulator] (store.js:688)
    at ScanSubscriber._tryNext (scan.js:49)
    at ScanSubscriber._next (scan.js:42)
    at ScanSubscriber.next (Subscriber.js:49)
    at WithLatestFromSubscriber._next (withLatestFrom.js:57)
    at WithLatestFromSubscriber.next (Subscriber.js:49)
但我想我已经复制了第1行中的状态本身。

let updatedEducationList = [...state.educationList];
我错过了什么

让updateeducationlist=[…state.educationList];
//现在updatedEducationList是一个新数组
//但它的每个元素都指向当前状态中的相关值。
//因为它不是深度克隆。
const targetIndex=updatedEducationList.findIndex((educationItem)=>{
返回educationItem.id==action.payload.educationId;
});
//现在,如果您选中state.educationList[targetIndex]==updatedEducationList[targetIndex],它将为true。
//尽管updatedEducationList==state,但educationList为false。
让oldDescription=updatedEducationList[targetIndex].description;
//现在它指向当前状态。
让newDescription=oldscription.filter((项目,索引)=>index!==action.payload.roleIndex);
//指向当前状态项的新指针数组。
updatedEducationList[targetIndex]。description=newDescription;
//错误,因为updatedEducationList[targetIndex]仍然指向当前状态。描述也是如此。
updatedEducationList[targetIndex]={…updatedEducationList[targetIndex],description:newDescription};
//对,因为它创建的新对象不再指向当前状态。只显示其键的值。
返回{…状态,educationList:updatedEducationList};
回答


对于包含其他对象或数组的对象和数组,复制这些对象需要深度复制。否则,对嵌套引用所做的更改将更改嵌套在原始对象或数组中的数据。在这种情况下,
description
是一个嵌套对象,因此在浅拷贝之后,它仍然指向内存中与原始状态相同的地址。为了便于阅读,编辑了这个问题。description是长度为1或2的数组。您的问题是为什么不能直接更改
updateeducationlist[targetIndex]。description=newDescription
?因为代码段中的代码看起来是正确的。是的。因为,我认为我不是直接修改状态,而是通过
return{…state,educationList:updateeducationlist}返回状态啊,我明白了。事实上是的。我会更新答案。1秒。完成,在每一行下面你可以找到它的作用的解释。