Mutable Immutable State with Immer

Immer is a library that allows us to act like mutating state is totally okay—mostly because we're not actually mutating it.

Here is a super simple example.

if (action.type === ITEM_ADDED) {
  return produce(state, (draftState) => {
    const item = {
      uuid: id++,
      quantity: 1,
      name: action.payload.name,
      price: parseInt(action.payload.price, 10),
    };

    draftState.push(item);
  });
}

If you look closely, you can see the following:

  • It takes the object you want to change and then a function where it passes it in as an object you can mutate.
  • After you're done, it returns a new object based on the changes you made the the draft object.

That's not particularly impressive with adding a new item. The spread operator wasn't huring anyone. But, what about, updating the price?

if (action.type === ITEM_PRICE_UPDATED) {
  return produce(state, (draftState) => {
    const item = state.find((item) => item.uuid === action.payload.uuid);
    item.price = parseInt(action.payload.price, 10);
  });
}

Exercise

This is where we our now.

Can you implement it for the quantity? (You can fine the solution here.)