繁体   English   中英

将 ES6 Map 与 React 和/或 Redux 一起使用

[英]Using ES6 Map with React and/or Redux

我正在考虑使用 ES6 Map对象为我进行散列,而不是创建自定义散列函数。 然而,在我看来,它对不变性的支持并不多,这对于 React 和 Redux 来说都是关键。

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

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

或使用数组映射/过滤。

但是,ES6 Map具有直接更新对象本身的方法。

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

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

但我不确定这是否可行。

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

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

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

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

我最近考虑使用 Map 数据结构和 react +redux 并决定反对它。

尽管在某些用例中使用 Map 有一点性能优势,但主要是因为编译器更清楚会发生什么。 你会免费获得一个尺寸道具 :)

我认为反对这种方法的原因更多:

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

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

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

React 并不太在意 :)

我在使用 Redux 的 React 项目中使用 ES6。

用例 #1

在一个组件内:

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

稍后当我需要更新数据时(例如,获取了新元素),我使用 Thunk 在 redux 中设置了一个loading标志,稍后又回到false触发更新。

我用新数据更新我的 ES6 地图,对其进行变异,但没有创建新地图。 我的组件由于loading标志而更新,并使用内部地图中的新数据重新渲染

用例 #2

在 Redux 状态

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

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

但是在每次更新时创建新地图只有在您不经常更新它但经常从中读取时才有用。

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

因此,我建议您找出使用 ES6 Map 有益的部分,以及与常规Object一起使用的部分。

在 state 内使用 ES6 的Map其实非常简单。 你需要使用ReactDOMReactDOM.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()可以正常工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM