Using Immer to Optimise Redux Reducer
Know how immer helped us in optimizing redux reducer file code in my organization
We will cover the below topics in this post:
- Introduction to immer
- Use cases of immer in our codebase and implementation
- How and when we should use immer
- Benefits of immer
Introduction to Immer
Immer is a tiny package that allows you to work with immutable
state in a more convenient way. Immer can be used in any context where we want to achieve immutability. For example in combination with React state, React or Redux reducers, or configuration management.
The word immutable
means unchanging over time or unable to be changed. Javascript objects are mutable
in nature but with immer we can achieve immutability
. Let’s understand this with an example:-
In the above example, we have used a produce
method that’s exposed by immer. The syntax of produce is:
produce(baseState, recipe: (draftState) => void): nextState
produce
takes a base state, and a recipe that can be used to 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
. So, we have a brand new state i.e. nextState
and there is no any dependency of baseState
on this.
Use Case of Immer in our Codebase and Implementation
We are using immer produce
method to optimize reducer file code. Let’s check what’s the problem without immer with a code snippet:
So, here we have a reducer called UPDATE_STREETNO_VISIBILITY
for updating streetno
visibility. The problem is with showStreetNo
which is deeply nested inside the response object, result
here. To retrieve the value, we'll have to use the spread operator multiple times - And that doesn't look good.
In JavaScript, objects are mutable — updating properties of a state object directly on the reference doesn’t change the object as a whole.
Therefore, it is usually recommended to always return a new state object from the reducer.
We can achieve immutability using immer which helps in optimizing code as well.
Let’s check with the code snippet:
Let’s implement withProduce
method:
As we can see, we have a withProduce
method that’s calls reducer
when an action get dispatched with draftState
.
The produce function receives one argument, the draft
, which is a proxy to the current state you passed in. Any modification you make to the draft will be recorded and used to produce nextState
. The currentState
will be untouched during this process.
We have optimized code in UPDATE_STREETNO_VISIBILITY
reducer as there is no need to make a new state object and maintain references with the spread operator.
Simply access the state with the dot operator and update the value.
Immer produce does all the work like maintaining references and updating the value.

How and When We Should Use Immer
Immer should be used when we have complex state and not easy to handle in a reducer file.
Immer has the ability to work with React Hooks. Immer uses an additional library called use-immer
to achieve this functionality.
This provides me with hooks like useImmer and useImmerReducer. You can find it here:
You can check more example about immer hooks here:-
Benefits of Immer
- Boilerplate reduction. Less noise, more concise code.
- Small: 3kb gzipped
- Deep updates are a breeze
- Follow the immutable data paradigm, while using normal JavaScript objects, arrays, Sets, and Maps. No new APIs or “mutation patterns” to learn!
- Performance of immer is higher as compared to other libraries like ImmutableJS
