immer 如何处理带有映射和集合的对象键?

How does immer handle object keys with maps and sets?

immer docs 状态 "The keys of a map are never drafted! This is done to avoid confusing semantics and keep keys always referentially equal",但我很难理解这是什么意思。

我预计这意味着使用草稿对象作为草稿 Map/Set 中的键会自动取消引用该键,就好像我调用了例如map.set(original(key) || key, value)。然而,事实并非如此,我不明白那句话是什么意思。

这里有一些例子可以证明我的意思。我预计所有这些日志 true

const { enableMapSet, produce } = immer;
enableMapSet();

const collection = {
  map: new Map(),
  set: new Set(),
  storedAsObject: {},
  storedAsDraft: {},
};

collection.set.add(collection.storedAsObject);
collection.map.set(collection.storedAsObject, 'value');

const newCollection = produce(collection, (draft) => {
  console.log(draft.set.has(draft.storedAsObject)); // false
  console.log(draft.map.has(draft.storedAsObject)); // false

  draft.set.add(draft.storedAsDraft);
  draft.map.set(draft.storedAsDraft, 'value');
});

console.log(newCollection.set.has(newCollection.storedAsDraft)); // true
console.log(newCollection.map.has(newCollection.storedAsDraft)); // false
<script src="https://unpkg.com/immer@6.0.3/dist/immer.umd.production.min.js"></script>

特别是,最后两个的差异似乎是一个错误,但文档中谈论的特殊行为只调用地图,所以我不确定。

这意味着如果您获取 Map 的键,并且它们是对象,您将不会取回草稿(就像您获取值时那样),而是取回原始对象。

所以你不应该改变地图中使用的键。 (例如 Array.from(draftMap.keys())[0].counter++ 之类的东西不会被 Immer 处理)