【问题标题】:ERROR TypeError: Cannot assign to read only property 'isSelected' of object '[object Object]'错误类型错误:无法分配给对象“[对象对象]”的只读属性“isSelected”
【发布时间】:2020-02-03 09:00:23
【问题描述】:

我只想在克隆后更新 My NgRx Store Object 中数组元素的属性值以避免突变但没有成功。 这是Reducer代码:

on(
    myActions.elementDeselected,
    (state, { desiredId}) => {
    const childArrayCopy=[...state.selectedObject.childArray.slice(0)];
    const childArray = childArrayCopy.map(arrayElement=> {
        if (arrayElement.id === desiredId) {
          arrayElement.isSelected = false;
          return arrayElement;
        }
        return arrayElement;
      });

      return {
        ...state,
        selectedObject: {
          ...state.selectedObject,
          ...childArray
        }
      };
    }
  ),

【问题讨论】:

    标签: angular typescript redux ngrx


    【解决方案1】:

    由于arrayElement 是只读的,您也必须复制

    const childArray = childArrayCopy.map(arrayElement=> {
      if (arrayElement.id === desiredId) {
        arrayElement = {...arrayElement, isSelected: false}; // <===
      }
      return arrayElement;
    });
    

    使用spread的对象属性版本创建一个带有旧对象属性副本的新对象,然后将isSelected更新为false

    【讨论】:

      【解决方案2】:

      不允许更改存储对象,您应该始终创建一个副本,也适用于嵌套对象:

      const childArray = childArrayCopy.map(arrayElement=> ({
        ...arrayElement,
        isSelected: arrayElement.id === desiredId ? false : arrayElement.isSelected
      }));
      

      【讨论】:

      • 即使不更新也需要创建副本吗?
      • @T.J.Crowder 绝对不是,但我喜欢紧凑的代码,可以立即看到 isSelected 属性是目标,并且鉴于同一循环中的一些额外相似的 ifs,它只会需要额外的一行而不是 3 行。但这只是个人喜好。虽然当它用于 +1000 个元素的数组并且经常运行时,确实建议对其进行优化
      • 好的,谢谢。我不确定这里是否存在我不知道的 Redux 微妙之处。 :-)
      • @T.J.Crowder 另外,如果不使用异步管道,并且角度组件使用arrayElement 作为对象的输入,并且组件使用OnPush,则很奇怪,可能是组件没有更新,因为对象的引用没有改变:)。我相信当有人在他们的组件代码中使用.subscribe 时,这也可能发生。所以主要是,当使用相对不好的实践代码时,你可能会遇到问题
      猜你喜欢
      • 1970-01-01
      • 2018-06-15
      • 1970-01-01
      • 2017-11-01
      • 2020-08-20
      • 1970-01-01
      • 2021-06-30
      • 2021-06-17
      • 2011-11-13
      相关资源
      最近更新 更多