Curried producers
egghead.io lesson 6: Simplify code by using curried _reduce_
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:
import {produce} from "immer"
function toggleTodo(state, id) {
return produce(state, draft => {
const todo = draft.find(todo => todo.id === id)
todo.done = !todo.done
})
}
const baseState = [
{
id: "JavaScript",
title: "Learn TypeScript",
done: true
},
{
id: "Immer",
title: "Try Immer",
done: false
}
]
const nextState = toggleTodo(baseState, "Immer")
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.
import {produce} from "immer"
// curried producer:
const toggleTodo = produce((draft, id) => {
const todo = draft.find(todo => todo.id === id)
todo.done = !todo.done
})
const baseState = [
/* as is */
]
const nextState = toggleTodo(baseState, "Immer")
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.