MobX React - 更新对象数组的单个索引会重新渲染所有子对象

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

我有一个 mobx 对象存储,这些对象显示在列表视图中,并在存储值上有一个地图,如下所示:

{ObjectStore.objects.map((obj, index) =>      
    <ObjectItem
       key={obj.id}
       obj={obj}
       objIndex={index}
       ...unrelated UI Pros 
    />
)}

在 ObjectItem 中有一个 onClick 处理程序,它向该特定对象添加一些新内容:

const handleClick = () => {     
    ObjectStore.updateObjectbyIdx(objIndex, newData) 
}

在商店

updateObjectbyIdx (index, data) {     
    this.objects[index] = { ...this.objects[index], ...data} 
}

两个 React 组件都包装在观察者中。当句柄单击运行时,它会导致父容器重新呈现,然后所有 ObjectItem 组件重新呈现,即使附加数据仅通过索引添加到单个项目。

最初我完全避免使用索引并使用地图更新它,如下所示:

updateObjectbyId (id, data) {     
    this.objects = this.objects.map(obj => obj.id === id ? { ...obj, ...data} : obj }) 
}

但我假设由于这是创建一个新的数组引用,因此父容器观察ObjectStore.objects重新渲染。

切换到索引让我期望父级不会重新渲染,因为主数组引用仍然存在,并且由于我在最新点解构了值,因此只有单个 ObjectItem 会重新渲染。

我最终确实让它发挥作用:

updateObjectbyIdx (index, data) {     
    Object.keys(data).forEach(dataKey => {         
        this.objects[index][dataKey] = data.dataKey     
    } 
}

但是,当我只想更新数组中单个对象中的数据时,这似乎是一个奇怪的解决方法。

reactjs observable mobx mobx-react
1个回答
0
投票

这样做:

updateObjectbyIdx (index, data) {     
    this.objects[index] = { ...this.objects[index], ...data} 
}

您还更新了对该对象的引用,并且由于父组件使用该对象,它将重新渲染。

您可以这样做

Object.assign

,而不是最后一个解决方案(实际上,这是正确且很好的)
updateObjectbyIdx (index, data) {     
    Object.assign(this.objects[index], data)
}

这将保留引用并仅更新属性。只需记住深层嵌套的属性、对象、数组即可。要处理它们,您最好使用某种

mergeDeep
函数,
Object.assign
不会进行合并,它基本上会覆盖您在自定义循环中所做的所有内容。

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