SIGN IN SIGN UP
immerjs / immer UNCLAIMED

Create the next immutable state by mutating the current one

28907 0 0 JavaScript
2019-09-12 20:18:26 +02:00
---
id: complex-objects
2019-10-31 09:59:56 +00:00
title: Working with Map, Set and classes
2019-09-12 20:18:26 +02:00
---
<div id="codefund"><!-- fallback content --></div>
2019-10-30 20:57:54 +00:00
Plain objects, arrays, `Map`s and `Set`s are always drafted by Immer. An example of using Maps with immer:
```javascript
test("Producers can update Maps", () => {
const usersById_v1 = new Map()
const usersById_v2 = produce(usersById_v1, draft => {
// Modifying a map results in a new map
draft.set("michel", {name: "Michel Weststrate", country: "NL"})
})
const usersById_v3 = produce(usersById_v2, draft => {
// Making a change deep inside a map, results in a new map as well!
draft.get("michel").country = "UK"
})
2019-10-30 21:06:49 +00:00
// We got a new map each time!
2019-10-30 20:57:54 +00:00
expect(usersById_v2).not.toBe(usersById_v1)
expect(usersById_v3).not.toBe(usersById_v2)
2019-10-30 21:06:49 +00:00
// With different content obviously
2019-10-30 20:57:54 +00:00
expect(usersById_v1).toMatchInlineSnapshot(`Map {}`)
expect(usersById_v2).toMatchInlineSnapshot(`
Map {
"michel" => Object {
"country": "NL",
"name": "Michel Weststrate",
},
}
`)
expect(usersById_v3).toMatchInlineSnapshot(`
Map {
"michel" => Object {
"country": "UK",
"name": "Michel Weststrate",
},
}
`)
2019-10-30 21:06:49 +00:00
// The old one was never modified
expect(usersById_v1.size).toBe(0)
// And trying to change a Map outside a producers is going to: NO!
expect(() => usersById_v3.clear()).toThrowErrorMatchingInlineSnapshot(
`"This object has been frozen and should not be mutated"`
)
2019-10-30 20:57:54 +00:00
})
```
2019-09-12 20:18:26 +02:00
Every other object must use the `immerable` symbol to mark itself as compatible with Immer. When one of these objects is mutated within a producer, its prototype is preserved between copies.
```js
import {immerable} from "immer"
class Foo {
[immerable] = true // Option 1
constructor() {
this[immerable] = true // Option 2
}
}
Foo[immerable] = true // Option 3
```
For arrays, only numeric properties and the `length` property can be mutated. Custom properties are not preserved on arrays.
When working with `Date` objects, you should always create a new `Date` instance instead of mutating an existing `Date` object.
2019-10-30 16:47:56 +00:00
Maps and Sets that are produced by Immer will be made artificially immutable. This means that they will throw an exception when trying mutative methods like `set`, `clear` etc. outside a producer.