这更多是一个通用的最佳实践问题。
我一直在使用JavaScript Maps到处游玩,并且一直在尝试查找有关是否将状态属性设置为Map的反模式/代码气味的更多信息。以下链接是Redux存储库中的问题线程,其中包含一些注释,例如:
“您可以将Maps和Sets用作状态值,但出于可序列化性的考虑,建议不要使用它。”
但是该线程与Redux有关。香草反应怎么样?任何人都有强烈的意见或见识?很抱歉,这个问题在错误的位置。
答案 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']]))
))