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

时间:2018-02-01 04:16:54

标签: javascript reactjs redux immutability

我在更新不可变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 个答案:

答案 0 :(得分: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的调用结构来确定相应的子阵列。

答案 1 :(得分:2)

尝试使用Immutability Helper

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

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

我试过了 Click Me

答案 2 :(得分:1)

这是一个较长的解决方案,但随着您的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};