不变违规:在路径中的调度之间检测到状态突变

问题描述 投票:0回答:1

我想将数组中的一项与另一项连接起来,并从数组中删除第二项。当我尝试旧方法时,出现状态突变检测错误。当我尝试

Object.assign
时,我无法连接值。

编辑: 使用

interests[makeIndex].value = ``${interests[makeIndex].value}, ${interests[secondPreferredMakeIndex].value}`` 
Object.assign
等效于什么?

例如,对于下面的代码段,我期望的输出是,

Preferred Make - before Chevrolet
Preferred Make - after Chevrolet, Porsche
// Interests array from state
let interests = [
  {
    type: 'Preferred Make',
    value: 'Chevrolet',
  },
  {
    type: 'Second Preferred Make',
    value: 'Porsche',
  },
  {
    type: 'Preferred Model',
    value: 'Corvette',
  },
  {
    type: 'Second Preferred Model',
    value: 'Macan',
  }
];

console.log("Preferred Make - before", interests[0].value);

const secondPreferredMakeIndex = interests
  .map(x => x.type)
  .indexOf('Second Preferred Make');

if (secondPreferredMakeIndex > -1) {
  let makeIndex = interests.map(x => x.type).indexOf('Preferred Make');

  if (makeIndex > -1) {
    // For the below, I get mutation error. But it works
    // interests[makeIndex].value = `${interests[makeIndex].value}, ${interests[secondPreferredMakeIndex].value}`;

    // Concatenate and use Object.assign to avoid mutation
    interests = Object.assign([], interests, { makeIndex: `${interests[makeIndex].value}, ${interests[secondPreferredMakeIndex].value}` });
    /*
    // Tried the below as well in vain
    interests = Object.assign([], interests, {
      makeIndex: {
        type: 'Preferred Make',
        value: `${interests[makeIndex].value}, ${interests[secondPreferredMakeIndex].value}`
      },
    });
    */
  }

  // Delete the second Preferred Make
  interests.splice(secondPreferredMakeIndex, 1);
}

console.log("Preferred Make - after", interests[0].value);

感谢帮助

javascript react-redux
1个回答
0
投票

问题

interests = Object.assign([], interests, { makeIndex: `${interests[makeIndex].value}, ${interests[secondPreferredMakeIndex].value}` });
正在重新分配状态值。

代码还会在对象上创建一个新的

makeIndex
属性,而不是更新
value
属性。

解决方案

您应该创建所选 interests 状态的“深层复制”(

将数组和数组元素复制到新的对象引用中
),因为您想要更新特定元素并从数组中删除元素。出于演示目的,我只是使用
JSON.parse(JSON.stringify(interests))
来“克隆”对象。

对于要更新的元素对象,请使用

value
键而不是
makeIndex

Object.assign(
  interestsCopy[makeIndex],
  {
    value: `${interestsCopy[makeIndex].value}, ${interestsCopy[secondPreferredMakeIndex].value}`
  }
);

// Interests array from state
let interests = [
  {
    type: 'Preferred Make',
    value: 'Chevrolet',
  },
  {
    type: 'Second Preferred Make',
    value: 'Porsche',
  },
  {
    type: 'Preferred Model',
    value: 'Corvette',
  },
  {
    type: 'Second Preferred Model',
    value: 'Macan',
  }
];

// "deep copy"
let interestsCopy = JSON.parse(JSON.stringify(interests));

console.log("Preferred Make - before (orig)", interests[0].value);
console.log("Preferred Make - before (copy)", interestsCopy[0].value);

const secondPreferredMakeIndex = interestsCopy
  .map(x => x.type)
  .indexOf('Second Preferred Make');

if (secondPreferredMakeIndex > -1) {
  let makeIndex = interestsCopy.map(x => x.type).indexOf('Preferred Make');

  if (makeIndex > -1) {
    Object.assign(
      interestsCopy[makeIndex],
      {
        value: [
          interestsCopy[makeIndex].value,  
          interestsCopy[secondPreferredMakeIndex].value
        ].join(", "),
      }
    );
  }

  // Delete the second Preferred Make
  interestsCopy.splice(secondPreferredMakeIndex, 1);
}

console.log("Preferred Make - after (orig)", interests[0].value);
console.log("Preferred Make - after (copy)", interestsCopy[0].value);

更正确的解决方案可能是将当前

interests
数组映射到具有要更新的新元素对象的新数组,然后从数组中过滤出旧元素。

示例:

// Interests array from state
let interests = [
  {
    type: 'Preferred Make',
    value: 'Chevrolet',
  },
  {
    type: 'Second Preferred Make',
    value: 'Porsche',
  },
  {
    type: 'Preferred Model',
    value: 'Corvette',
  },
  {
    type: 'Second Preferred Model',
    value: 'Macan',
  }
];

const interestsCopy = interests.map(({ type, value }, index, arr) => {
  switch(type) {
    case "Preferred Make":
      return {
        type,
        value: [
          value,
          arr.find(el => el.type === "Second Preferred Make")?.value
        ]
          .filter(Boolean)
          .join(", "),
      };

    default:
      return { type, value };
  }
}).filter(({ type }) => type !== "Second Preferred Make");

console.log("Preferred Make - after (orig)", interests[0].value);
console.log("Preferred Make - after (copy)", interestsCopy[0].value);

© www.soinside.com 2019 - 2024. All rights reserved.