0

给定下面的状态对象

{
  colour: ['red', 'blue', 'green'],
  size: ['small', 'medium', 'large'],
  position: ['bottom', 'top', 'left', 'right'],
}

我需要能够更改/更新其属性值attrValues以及属性键attrKey

我正在使用以下逻辑来做到这一点:

setAttributes((prevState) => {
  const key = Object.keys(attributeToUpdate)[0];
  if (key !== attrKey) {
    delete prevState[key];
  }
  return { ...prevState, [attrKey]: attrValue };
});

如果我将属性键更改为colourcolor可以工作,但结果状态更改为:

{
  size: ['small', 'medium', 'large'],
  position: ['bottom', 'top', 'left', 'right'],
  color: ['red', 'blue', 'green'],
}

color属性移动到最后,我想将其保持在原来的位置。

任何帮助或指示将不胜感激。

4

2 回答 2

2

尽管应该考虑到对密钥插入顺序/优先级的表达担忧,但 OP 正在寻找的解决方案可能接近于下一个提供的代码......

function renamePropertyAndKeepKeyPrecedence(obj, [oldKey, newKey]) {
  const descriptors = Object.getOwnPropertyDescriptors(obj);
  if (descriptors.hasOwnProperty(oldKey)) {
    Object
      .entries(descriptors)
      .reduce((target, [key, descriptor]) => {

        // delete every property.
        Reflect.deleteProperty(target, key);

        if (key === oldKey) {
          // rename addressed key.
          key = newKey;
        }
        // reassign every property.
        Reflect.defineProperty(target, key, descriptor)

        return target;

      }, obj);
  }
  return obj;
}

const sample = {
  position: ['bottom', 'top', 'left', 'right'],
  colour: ['red', 'blue', 'green'],
  size: ['small', 'medium', 'large'],
};
console.log('before property renaming ...', { sample });

renamePropertyAndKeepKeyPrecedence(sample, ['colour', 'color']);
console.log('after property renaming ...', { sample });
.as-console-wrapper { min-height: 100%!important; top: 0; }

于 2021-12-03T12:06:34.637 回答
1

您无法控制对象中键的顺序 - 如果顺序很重要,您应该有一个对象数组。然后,您可以重建已删除您想要的项目并替换它的状态。

下面的演示在实践中展示了这一点:

let prevState = [
  {key:"colour",values: ['red', 'blue', 'green']},
  {key:"size", values:['small', 'medium', 'large']},
  {key:"position",values:['bottom', 'top', 'left', 'right']}
]

const indexToRemove = prevState.findIndex(x => x.key == "colour");

prevState = [
  ...prevState.slice(0,indexToRemove),
  {key:"color", values:['red', 'blue', 'green']},
  ...prevState.slice(indexToRemove+1)
]
console.log(prevState)

因此,如果我理解您的代码,则更正将是

setAttributes((prevState) => {
  const key = Object.keys(attributeToUpdate)[0];
  const indexToRemove = prevState.findIndex(x => x.key == key);

  return [
    ...prevState.slice(0,indexToRemove),
    {key:attrKey, values:attrValue},
    ...prevState.slice(indexToRemove+1)
  ]
});

而且您必须更新其余代码以使用状态数组而不是对象。

于 2021-12-03T11:15:55.420 回答