将 ES6 Map 与 React 和/或 Redux 结合使用

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

我正在考虑使用 ES6

Map
对象来为我进行哈希处理,而不是创建自定义哈希函数。然而,在我看来,它对不变性没有太多支持,而这对于 React 和 Redux 来说都是关键。

我习惯不使用任何库来实现不变性,而只使用简单的解构:

const newObj = { ...prevObj, newKey: "value" }

或使用数组进行映射/过滤。

但是,ES6

Map
有直接更新对象本身的方法。

我能想到的是做这样的事情:

var myMap = new Map()
Var myNewMap = { ...myMap.set() }
this.setState({ myMap:myNewMap })

但我不确定这是否有效。

javascript reactjs dictionary redux react-redux
6个回答
6
投票

如果您只想要类型安全的键值存储,可以使用以下语法:

entities: { [id: number]: MyEntity },
...

5
投票

我最近考虑过将 Map 数据结构与 React +Redux 结合使用,但决定不这样做。

尽管对于某些用例来说,使用 Map 会带来轻微的性能优势,主要是因为编译器更清楚地知道会发生什么。 您还可以免费获得一个尺寸道具:)

我认为反对这种方法还有更多理由:

首先,redux 不喜欢不可序列化的对象 - faq。如果你想使用 SSR 或将数据保存在 localStorage 中,它将不起作用。

您无法享受 redux 工具包中的许多功能,因为它们假设/创建简单的对象数据结构。例如 createEntityAdapter - 我个人认为很棒

您可以在每个减速器中创建一个新地图,但它可能很快就会变得烦人,而且我不确定性能。

React 并不太关心:)


0
投票

JavaScript 中的所有对象本质上都是引用类型 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#comparing_objects)。 Redux 中状态对象不可变的唯一原因是库本身不允许您直接修改

getState
返回的状态对象。

此外,JavaScript 对象本身就是一个字典,因此通过属性名称从该状态对象中获取数据仍然是 O(1) 时间复杂度


0
投票

如果你想在 Redux 中使用类似映射的结构,它是可序列化的、O(1)且语法高效的——使用枚举作为键,这就是我所做的:

export type MapLikeType = {
  [K in EnumType]?: valueType;
};

-2
投票

我在 React 项目中使用 ES6,该项目也使用 Redux。

用例#1

在组件内:

我收到数据,然后我需要处理它,例如向每个元素添加一些标志和/或附加参数,然后我将其作为 ES6 Map 存储在组件中(不在组件状态中)。

稍后,当我需要更新数据时(例如,获取新元素),我使用 Thunk 在 redux 中设置

loading
标志,稍后返回到
false
触发更新。

我用新数据更新我的 ES6 Map,对其进行变异,但不创建新的 Map。 我的组件由于

loading
标志而得到更新,并使用内部 Map 中的新数据重新渲染

用例#2

处于 Redux 状态

我的 Redux 状态有一个 ES6 Map,因为我想与多个组件共享它。 我像在减速器中一样保持它不可变:

const newMap = new Map(oldMap.entries())

但是,只有在您不经常更新但经常从中读取数据的情况下,在每次更新时创建新地图才有用。

在我的例子中,我必须在 Redux 状态下使用 Map,因为 ES6 Map 保持元素的order,同时提供对它们的 O(1) 访问。

所以我建议你弄清楚哪些部分使用 ES6 Map 是有利的,哪些部分可以使用常规

Object


-4
投票

在状态下使用ES6的

Map
其实非常简单。您需要使用
ReactDOM
ReactDOM.render(document.getElementById('someid'), map.get("123"));
。但要使其在优化方面具有任何优势,就有点复杂了。它可能只对某些应用程序有用。

为了避免严格抽象,让我们看一个示例应用程序:DOM 是一个 HTML

<table>
,ReactJS 状态是一个
Map
坐标和值。
<td>
元素将具有坐标 ID,例如
id="pos-1,2"
是第一行第二列的位置。现在该州可能看起来像......

this.state = {
    'coordinates': Map({'1,2':'my 1/2 text!', '4,5':'my 4/5 text!'}),
};

要更新状态,您可以有

updateState()
...

updateState(newmap) {
    const coordinates = this.state.coordinates;
    newmap.keys().forEach((key) => {
        const parent = document.getElementById('pos' + key);
        const text = newmap.$key;
        ReactDOM.unmountComponentAtNode(parent);
        ReactDOM.render(parent, (<span>{text}</span>);
        coordinates.set(key, text);
    });
    this.state.setState({'coordinates':coordinates});
}

那么,这里发生了什么?我们可以随时在表格网格上的任何位置更新状态。例如,如果我们已经有 500 个带有文本的网格,我可以再添加一个带有

this.updateState(Map({'1000,500':'my text at position 1000x500!'}));
的网格文本字段。通过这种方式,
Map()
可以在状态中使用,它保留了对单个更改进行 O(1) 查找的好处,因为我们的
updateState()
可以处理它。

这也绕过了

render()
的大部分使用,但这是一个设计决策。我使用了 1,000x1,000 表格网格的示例,因为使用
render()
时,拥有 1,000^2 个独特的有状态元素会产生巨大的负载/处理时间,在这种情况下,
Map()
就可以正常工作。

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