【问题标题】:Using ES6 Map with React and/or Redux将 ES6 Map 与 React 和/或 Redux 一起使用
【发布时间】:2019-05-16 17:36:30
【问题描述】:

我正在考虑使用 ES6 Map 对象为我做哈希,而不是创建自定义哈希函数。但是,在我看来,它对不变性的支持并不多,这对于 React 和 Redux 来说都是一个关键。

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

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

或使用数组映射/过滤。

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

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

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

但我不确定这是否可行。

【问题讨论】:

  • 我会避免在 redux 商店中使用 Map。 github.com/reduxjs/redux/issues/1499
  • 好的,但是我将如何获得与 0(1) 查找相同的好处?
  • 有兴趣知道您在做什么,其中地图在对象上的查找速度会有所不同,值得担心。您是否一次查找数十万个值?
  • 嗯,这个问题的答案有两个方面。我处于一个必须编写一个 Web 应用程序的位置,该应用程序将由位于与 VM 的 RDP 连接上的用户使用,这极大地降低了客户端的处理能力,并且 javascript 的运行速度比以往任何时候都慢。因此,如果我可以节省任何时间来查找 redux,我将获得很多。其次,我可能或现在有大约 80-120.000 行需要搜索的客户记录的缓存数据,因此我认为缩短搜索时间而不是进行数据库查找可能会有所帮助。
  • 我想唯一的问题是,你真的遇到过使用普通对象的问题吗?如果不是,那么这可能是一个过早的优化。如果是这样,那么您可能想要查看一些 redux 的替代方案,即使只是针对有问题的数据。似乎在 Redux 中使 Maps 工作的复杂性不值得付出努力,甚至可能抵消 Maps 的好处,例如创建新 Maps 比创建对象慢得多。在投入大量工作之前,绝对值得进行一些实际测量。

标签: javascript reactjs dictionary redux react-redux


【解决方案1】:

在状态内使用 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() 可以正常工作。

【讨论】:

  • 我认为有误会。问题是关于the Map object,但这个答案是关于the Array.prototype.map() function。相似的名字,不同的概念。
  • 嗨,Kostas:感谢您的提醒,我为 map 添加了一些大写字母为 Map(),现在应该修复了。
【解决方案2】:

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

用例 #1

在一个组件内:

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

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

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

用例 #2

在 Redux 状态

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

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

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

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-02-05
        • 2017-12-09
        • 2018-12-05
        • 2018-06-10
        • 1970-01-01
        • 2018-02-03
        • 1970-01-01
        相关资源
        最近更新 更多