【问题标题】:trying to update an existing object in array of objects using react尝试使用反应更新对象数组中的现有对象
【发布时间】:2021-04-11 18:17:39
【问题描述】:

我有对象数组,格式是这样的

 addedOpaqueMaterials = [{
            conductivity: 1
            density: 1
            id: "1"
            ......
            ......
         },
         {
             conductivity: 2
             density: 1
             id: "2",
             ......
             ......
         }]

从反应状态我得到更新的对象 id= 2 如下所示,

{
    conductivity: 4
    density: 23
    id: "2",
    ......
    ......
}

我希望用这些值更新主数组中的对象,最好的更新方法是什么,下面是与此相关的代码。

const handleDrawerSubmit = values => {
   const addedOpaqueMaterials = formValues.constructionSet?.opaqueMaterials; // array of objects

   const updatedMaterial = addedOpaqueMaterials.find(i => i.id === values?.opaqueMaterial?.id);
   // values?.opaqueMaterial is having updated object
    
   // Object.assign(updatedMaterial, values.opaqueMaterial); getting an error      
};

现在我想将 values.Opaquematerial 对象合并到 addedOpaqueMaterials 对象数组中,实现此目的的最佳方法是什么?

非常感谢

【问题讨论】:

标签: javascript arrays reactjs object ecmascript-6


【解决方案1】:

这只是一个常规的算法挑战。没必要再想了。 react 对你的唯一要求是它需要是一个新数组。 Array#map 工作得很好。

const materialExists = addedOpaqueMaterials.some(({id}) => id === values?.opaqueMaterial?.id)
let updatedMaterial
if (materialExists) {
    updatedMaterial = addedOpaqueMaterials.map(material => {
        if (material.id === values?.opaqueMaterial?.id) {
            return values.opaqueMaterial
        }
        return material
    })
} else {
    updatedMaterial = [...addedOpaqueMaterials, values.opaqueMaterial]
}

【讨论】:

    【解决方案2】:

    不要使用.find,而是先使用.findIndex,这样就可以用新对象替换数组中的对象。 (记住当第一个参数是有状态的时候不要在 React 中使用Object.assign,因为那会导致状态突变)

    在尝试更新之前,您还应该先检查所有这些对象是否存在。

    if (!formValues.constructionSet || !values || !values.opaqueMaterial) {
      return;
    }
    const newMat = values.opaqueMaterial;
    const index = addedOpaqueMaterials.findIndex(mat => mat.id === newMat.id);
    if (index === -1) {
      // Add to the end of the existing array:
      const newOpaqueMaterials = [
        ...addedOpaqueMaterials,
        newMat
      ];
      // put newOpaqueMaterials into state
    } else {
      // Replace the object in the state array with the new object:
      const newOpaqueMaterials = [
        ...addedOpaqueMaterials.slice(0, index),
        newMat,
        ...addedOpaqueMaterials.slice(index + 1)
      ];
      // put newOpaqueMaterials into state
    }
    

    【讨论】:

    • 你应该修改你的变量声明。在 if 块内声明将使数组在需要的地方不可用。编辑:对不起,我没有看到你的评论。在ifelse 中进行相同的操作似乎有点奇怪,但它是可行的。
    • @Andrew OP 没有显示他如何更新状态,或者他是否正在使用钩子或类组件。他可能能够将出现的// put newOpaqueMaterials into state 替换为setMaterials(newOpaqueMaterials) 或等效项,这不需要修改答案中使用的范围。
    • 根据索引是否为-1,新数组的构造有些不同。是的,我想您可以使用条件运算符将其全部放入一个语句中(或使用let,ew),但我真的认为单独的块使代码的意图更清晰。
    • 不时使用let 并不是世界上最糟糕的事情。另一个选项是 do 表达式,但如果你假设他们有 babel 配置,那只会是一个答案。
    猜你喜欢
    • 2020-10-29
    • 2023-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-29
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    相关资源
    最近更新 更多