Skip to content
Logo Theodo

Reduce redux boilerplate with redux-toolkit

Daniel Tchangang5 min read

Reduce redux boilerplate with redux-toolkit

You’re looking for an easier way to write your reducer, aren’t you ?

When writing plain redux, you have to define an action, an actionCreator and a reducer to update the store of your app. The reducer is in most cases a big switch to handle all the actions dispatched by actionCreators in your app. This leads to a lot of boilerplate and make the code more difficult to understand. There are many librairies out there aiming to reduce this boilerplate.

At Theodo, we used typesafe-actions to reduce redux boilerplate. The redux team recently recommended @redux-toolkit as the “official recommended approach for writing Redux logic”. Thus, I tested it and wrote this article to show you the advantages of such librairies through a simple example.


The example

Screenshot de l'application développée

The example consist in changing the owner of a car :

  • There is one car and 2 possible owners (“JOHN” or “JANE”).
  • When you click on one of the owner, the car owner in the redux store is changed to match the owner clicked.

Plain redux (28 lines)

With plain redux as on the code below, there are :

base-redux-example-screenshot.png

The first simplification external librairies provide is to get rid of the action and avoid the switch in the reducer function.

Both typesafe-actions and redux/toolkit give you two functions to simplify action and reducer : createAction and createReducer

  • We do not need to keep the UPDATE_OWNER action type anymore in an variable to handle it in the reducer.
  • The switch disapears
  • Code is easier to read and understand

Typesafe action (21 lines ~ -25%)

example-with-type-safe-actions.png

example-with-type-safe-actions-2.png

const counterReducer = createReducer(0)
  .handleAction([add, increment], (state, action) =>
    state + (action.type === 'ADD' ? action.payload : 1)
  )
  .handleAction(add, (state=> action) => ...);

The code is clearer and easier to understand

Remarks :
- @reduxjs/toolkit provides also a `createAction` function but used in a slightly different manner see here.
- @reduxjs/toolkit `createReducer` function is used as typesafe-action

@redux/toolkit (18 lines ~ -35%)

example-with-redux-toolkit.png

No need to duplicate the state with spread operators everywhere: You can directly update the state and ImmerJs will take into account the changes and create a new state from the precedent state + the changes you made. Have a look again to the reducer function 👇🏽

const { actions, reducer: itemReducer } = createSlice({
  name: "items",
  initialState: initialItemState,
  reducers: {
    updateOwner: (state: ItemState, { payload: { user, item } }: UpdateOwnerAction) => {
      // This long code with many ... is replaced by one line thks to ImmerJS
      // return {
      // ...state,
      // [item.id]: { ...state[item.id], owner: user }
      // }
      state[item.id].owner = user;
    }
  }
});

This makes reducer and actions easier to understand. Goodbye "desctructuration ..." 😍.

⚠️ Redux teams recommends to read ImmerJs pitfalls before using it, so read it 😉


In the last example I use the createEntityAdapter function : the entityAdapter “generates a set of prebuilt reducers and selectors for performing CRUD operations on a normalized state structure.”

After normalizing my itemState and creating the itemsAdapter, I can simplify my reducer function to use the generic entityAdapter.updateOne to handle the ownerUpdate action (check full code here).

example with @/redux-toolkit and createEntityAdapter function.png

This gives you a very fast way to write your reducer logic.

Have a look at redux-toolkit doc to fully understand the createEntityAdapter API

Conclusion :

Reasons to use typesafe-actions

Reasons to use redux/toolkit

As redux/toolkit is the recommended library by the redux team, you should give it a try. Slicers + ImmerJS = 🔥 : your code is shorter and easier to understand. Moreover the createEntityAdapter will help you to normalize your state and write a new reducer faster thanks to the many CRUD functions provided.

Liked this article?