You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: website/docs/curried-produce.mdx
+36-41Lines changed: 36 additions & 41 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,8 @@ title: Curried producers
9
9
data-ea-type="image"
10
10
className="horizontal bordered"
11
11
></div>
12
-
</center> <details>
12
+
</center>
13
+
<details>
13
14
<summaryclassName="egghead-summary">
14
15
egghead.io lesson 6: Simplify code by using curried _reduce_
15
16
</summary>
@@ -30,56 +31,50 @@ title: Curried producers
30
31
</a>
31
32
</details>
32
33
33
-
Passing a function as the first argument to `produce` is intended to be used for currying. This means that you get a pre-bound producer that only needs a state to produce the value from. The producer function gets passed in the draft and any further arguments that were passed to the curried function.
34
-
35
-
For example:
34
+
Passing a function as the first argument to `produce` creates a function that doesn't apply `produce` yet to a specific state, but rather creates a function that will apply `produce` to any state that is passed to it in the future. This generally is called _currying_. Take for example the following example:
36
35
37
36
```javascript
38
-
// mapper will be of signature (state, index) => state
39
-
constmapper=produce((draft, index) => {
40
-
draft.index= index
41
-
})
37
+
importproducefrom"immer"
38
+
39
+
functiontoggleTodo(state, id) {
40
+
returnproduce(state, draft=> {
41
+
consttodo=draft.find(todo=>todo.id=== id)
42
+
todo.done=!todo.done
43
+
})
44
+
}
45
+
46
+
constbaseState= [
47
+
{
48
+
id:"JavaScript",
49
+
title:"Learn TypeScript",
50
+
done:true
51
+
},
52
+
{
53
+
id:"Immer",
54
+
title:"Try Immer",
55
+
done:false
56
+
}
57
+
]
42
58
43
-
// example usage
44
-
console.dir([{}, {}, {}].map(mapper))
45
-
//[{index: 0}, {index: 1}, {index: 2}])
59
+
constnextState=toggleTodo(baseState, "Immer")
46
60
```
47
61
48
-
This mechanism can also nicely be leveraged to further simplify our example reducer:
62
+
The above pattern of `toggleTodo` is quite typical; pass an existing state to `produce`, modify the `draft`, and then return the result. Since `state` isn't used for anything else than passing it on to `produce`, the above example can be simplified by using the _curried_ form of `produce`, where you pass `produce` only the recipe function, and `produce` will return a new function that will apply recipe to the base state. This allows us to shorten the above `toggleTodo` definition.
49
63
50
64
```javascript
51
65
importproducefrom"immer"
52
66
53
-
constbyId=produce((draft, action) => {
54
-
switch (action.type) {
55
-
caseRECEIVE_PRODUCTS:
56
-
action.products.forEach(product=> {
57
-
draft[product.id] = product
58
-
})
59
-
return
60
-
}
67
+
// curried producer:
68
+
consttoggleTodo=produce((draft, id) => {
69
+
consttodo=draft.find(todo=>todo.id=== id)
70
+
todo.done=!todo.done
61
71
})
62
-
```
63
-
64
-
Note that `state` is now factored out (the created reducer will accept a state, and invoke the bound producer with it).
65
-
66
-
If you want to initialize an uninitialized state using this construction, you can do so by passing the initial state as second argument to `produce`:
67
72
68
-
```javascript
69
-
importproducefrom"immer"
73
+
constbaseState= [
74
+
/* as is */
75
+
]
70
76
71
-
constbyId=produce(
72
-
(draft, action) => {
73
-
switch (action.type) {
74
-
caseRECEIVE_PRODUCTS:
75
-
action.products.forEach(product=> {
76
-
draft[product.id] = product
77
-
})
78
-
return
79
-
}
80
-
},
81
-
{
82
-
1: {id:1, name:"product-1"}
83
-
}
84
-
)
77
+
constnextState=toggleTodo(baseState, "Immer")
85
78
```
79
+
80
+
Note that the `id` param has now become part of the recipe function! This pattern of having curried producers combines really neatly with for example the `useState` hook from React, as we will see on the next page.
0 commit comments