Skip to main content

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.