React:将状态设置为es6 Map

时间:2018-12-04 04:35:22

标签: javascript reactjs dictionary

这更多是一个通用的最佳实践问题。

我一直在使用JavaScript Maps到处游玩,并且一直在尝试查找有关是否将状态属性设置为Map的反模式/代码气味的更多信息。以下链接是Redux存储库中的问题线程,其中包含一些注释,例如:

“您可以将Maps和Sets用作状态值,但出于可序列化性的考虑,建议不要使用它。”

但是该线程与Redux有关。香草反应怎么样?任何人都有强烈的意见或见识?很抱歉,这个问题在错误的位置。

https://github.com/reduxjs/redux/issues/1499

2 个答案:

答案 0 :(得分:5)

反应状态应该是不可变的,因为React使用浅比较来检查是否相等。比较标量值(数字,字符串)时,将比较它们的值。比较对象时,它不会比较它们的属性-只会比较它们的引用(例如“它们指向同一对象吗?)。

ES6 Maps不是不变的,并且针对可变性进行了优化,这就是为什么不建议在React中直接使用它们的原因。 React不会知道地图是否已更新。

var map1 = new Map();
var map2 = map1.set('b', 2); // mutate map
map1 === map2; // true because reference remain unchanged after mutation

如果需要,您可以使用地图,但需要使用一些不变性帮助器,例如Immutable.js。以下示例使用immutable map

const { Map } = require('immutable');
const map1 = Map({ a: 1, b: 2, c: 3 });
const map2 = map1.set('b', 2); // Set to same value
map1 === map2; // true
const map3 = map1.set('b', 4); // Set to different value
map1 === map3; // false

参考:

https://github.com/reduxjs/redux/issues/1499#issuecomment-194002599 https://stackoverflow.com/a/36084891/2073920

答案 1 :(得分:4)

如果您不想使用不可变库,则可以在更改时创建新的地图:

const [someMap, setSomeMap] = useState(new Map());

当您需要更新它时:

setSomeMap(new Map(someMap.set('someKey', 'a new value'));

相同的概念适用于Redux:

case 'SomeAction':
  return new Map(state.yourMap.set('someKey', 'a new value'))

关于可序列化性,它与本地状态无关。好的做法是拥有一个可序列化的Redux存储。

我可以将功能,承诺或其他不可序列化的商品置于商店状态吗?

强烈建议您只放置普通的可序列化对象, 数组和图元放入您的商店。从技术上讲 将不可序列化的商品插入商店,但是这样做可能会破坏 持久性和补给存储内容的能力 会干扰时间旅行调试。

如果您对持久性和时间旅行调试之类的东西没问题 可能无法按预期工作,那么我们完全欢迎您 将不可序列化的商品放入您的Redux商店。最终, 您的应用程序以及如何实现它取决于您。和许多一样 关于Redux的其他事情,只要确保您了解什么折衷 参与其中。

很不幸,您可以看到JSON.stringify在地图上不起作用:

console.log(JSON.stringify(
  new Map([['key1', 'value1'], ['key2', 'value2']])
))

如果您可以在序列化过程之间进行操作,则可以使用Array.from

console.log(JSON.stringify(
  Array.from(new Map([['key1', 'value1'], ['key2', 'value2']]))
))