0

The immer docs state "The keys of a map are never drafted! This is done to avoid confusing semantics and keep keys always referentially equal", but I'm having a tough time understanding what is meant by this.

I expected this to mean that using a draft object as a key in a draft Map/Set would automatically dereference the key as though I had called e.g. map.set(original(key) || key, value). However, that doesn't seem to be the case, and I can't figure what is meant by that statement.

Here are some examples that demonstrate what I mean. I expected true for all of these logs.

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>

In particular, the difference in the last two seems like a bug, but the special behavior the docs are talking about only call out maps, so I'm not sure.

Matt Tingen
  • 118
  • 7

1 Answers1

1

It means that if you'd grab the keys of a Map, and they are objects, you won't get drafts back, (like you would if you grab the values) but the original objects instead.

So you shouldn't mutate the keys used in the map. (e.g. things like Array.from(draftMap.keys())[0].counter++ won't be processed by Immer)

mweststrate
  • 4,890
  • 1
  • 16
  • 26