React惯用方式来更新状态中的Map对象

时间:2019-01-11 19:18:04

标签: javascript reactjs

我正在使用Map类。

我有这样的状态:

{
    rows: new Map([])
}

每一行代表一个表中的一个条目。 我想以线程安全的方式独立和异步地更新每一行。

在每次修改都是这样的情况下(假设“ fooId”已经插入到Map中),执行setState的惯用React方法是什么:

const rows = this.state.rows;
const row = rows.get("fooId");
row.status = '75%';

this.setState({
    rows: rows
});

1 个答案:

答案 0 :(得分:1)

惯用的方法是使用功能setState(),因为您要更新现有值而不是批量替换。

this.setState((prevState) => {
  const nextRows = new Map(prevState.rows)
  // Creating a new Map this way does not clone the original data
  // This means that any update to an object in the map will update the previous map.
  // To avoid this, we create a new object using object spread and assign the updated value there.
  // This has the benefit of reducing memory allocations as well, if performance is your concern.
  // Though it should not be until you have proven it to be a concern.
  const nextEntry = {
    ...nextRows.get('fooId'),
    status: '75%'
  }
  return { rows: nextRows.set('fooId', nextEntry) }
})

使用ImmutableJS可以使此操作变得容易一些

this.setState(prevState => ({ 
  rows: prevState.rows.update('fooId', entry => ({ ...entry, status: '75%' }))
}))

此外,只需要与@Jonas所说的矛盾即可:克隆地图时,它仅会克隆键和地图值之间的映射。它不会克隆地图的值。这意味着所需的内存消耗比您想象的要低得多。

如果您确定不会使用旧地图或旧地图中引用的任何对象,则甚至可以取消使用object-spread和您只会承担复制键/值映射(和创建新对象)的影响。如果您错了(可能很容易出错),这可能会导致一些真正令人困惑的错误,因此我会坚持使用不变的东西。

如果此确实成为性能问题,则可以以其他方式构造数据,以使变更分配更少。