更新对象的嵌套数据数组(Redux)

IT技术 javascript reactjs redux immutability
2021-05-14 22:41:39

我在更新不可变的 redux 和完全嵌套的数据时遇到问题。这是我的数据结构和我想要更改的示例。如果有人可以向我展示使用 ES6 和扩展运算符访问此更新的模式,我将不胜感激。😀

const formCanvasInit = {
  id: guid(),
  fieldRow: [{
    id: guid(),
    fieldGroup: [
      { type: 'text', inputFocused: true }, // I want to change inputFocused value
      { type: 'text', inputFocused: false },
    ],
  }],

  // ...
};
3个回答

这应该可以解决问题,假设数据完全按照所示设置,使用给定的数组索引:

const newData = {
   ...formCanvasInit,
   fieldRow: [{
      ...formCanvasInit.fieldRow[0],
      fieldGroup: [
         { ...formCanvasInit.fieldRow[0].fieldGroup[0], inputFocused: newValue },
         ...formCanvasInit.fieldRow[0].fieldGroup.slice(1, formCanvasInit.fieldRow[0].fieldGroup.length)
      ]
   }]
};

如果要动态确定要更改的元素的索引,则需要使用诸如filter查找和删除要更新的数组元素之类的功能,然后通过编辑对 的调用结构来扩展相应的子数组slice

尝试使用不变性助手

我认为在你的结构中,像这样

let news = update(formCanvasInit, {
  fieldRow: [{
    fieldGroup: [
     { $set: {type: "number", inputFocused: false}}
    ]
  }]
})

我试过了 点击我

这是一个较长的解决方案,但随着您的 redux 状态的增长可能会对您有所帮助。我还更改了原始状态下的一些值,以做出更清晰的解释。

const formCanvasInit = {
  id: 'AAAAXXXX',
  fieldRow: [
    {
      id: 1001,
      fieldGroup: [
        {type: 'text1', inputFocused: true}, // I want to change inputFocused value
        {type: 'text2', inputFocused: false},
      ]
    },
    {
      id: 1002,
      fieldGroup: [
        {type: 'text3', inputFocused: true},
        {type: 'text4', inputFocused: true},
      ]
    }
  ]
};

// the id of the field row to update
const fieldRowID = 1001;
// the value of the field type to update
const fieldTypeValue = 'text1';
const fieldRow = [...formCanvasInit.fieldRow];

// obtain the correct fieldRow object
const targetFieldRowIndex = formCanvasInit.fieldRow.findIndex(fR => fR.id === fieldRowID);
let fieldRowObj = targetFieldRowIndex && formCanvasInit.fieldRow[targetFieldRowIndex];

// obtain that fieldRow object's fieldGroup
const fieldGroup = [...fieldRowObj.fieldGroup];

// obtain the correct object in fieldGroup
const fieldIndex = fieldGroup.findIndex(fG => fG.type === fieldTypeValue);
const fieldToChange = fieldIndex && fieldGroup[fieldIndex];

// replace the old object in selected fieldGroup with the updated one
fieldGroup.splice(fieldIndex, 1, {...fieldToChange, inputFocused: false});

// update the target fieldRow object
fieldRowObj = {...fieldRowObj, fieldGroup};

// replace the old fieldGroup in selected fieldRow with the updated one
fieldRow.splice(targetFieldRowIndex, 1, fieldRowObj);

// create the new formCanvasInit state
const newFormCanvasInit = {...formCanvasInit, fieldRow};