Using produce
The Immer package exposes a default function that does all the work.
produce(currentState, recipe: (draftState) => void): nextState
produce
takes a base state, and a recipe that can be used perform all the desired mutations on the draft
that is passed in. The interesting thing about Immer is that the baseState
will be untouched, but the nextState
will reflect all changes made to draftState
.
Inside the recipe, all standard JavaScript APIs can be used on the draft
object, including field assignments, delete
operations, and mutating array, Map and Set operations like push
, pop
, splice
, set
, sort
, remove
, etc.
Any of those mutations don't have to happen at the root, but it is allowed to modify anything anywhere deep inside the draft: draft.todos[0].tags["urgent"].author.age = 56
Note that the recipe function itself normally doesn't return anything. However, it is possible to return in case you want to replace the draft
object in it's entirety with another object, for more details see returning new data.
#
Example#
Terminology(base)state
, the immutable state passed toproduce
recipe
: the second argument ofproduce
, that captures how the base state should be "mutated".draft
: the first argument of anyrecipe
, which is a proxy to the original base state that can be safely mutated.producer
. A function that usesproduce
and is generally of the form(baseState, ...arguments) => resultState
Note that it isn't strictly necessary to name the first argument of the recipe draft
. You can name it anything you want, for example users
. Using draft
as a name is just a convention to signal: "mutation is OK here".