Introduce redux-thunk-routine: Less boilerplate code and better static typing with redux-thunk

Thor Chen
3 min readJul 23, 2019

TLDR;

npm install redux-thunk-routine

Motivation

redux-thunk gives us the ability to create asynchronous actions, but do you feel that you are writing boilerplate code again and again?

Do you feel things are getting even worse when you trying to add static typing?

Inspired by redux-saga-routines which is a library for redux-saga, we have redux-thunk-routine for redux-thunk!

So what is a routine? Let's explain it with an example.

Understand routine in 1 minute

Imagine that we are creating an asynchronous action to fetch data using API, we might write the code like below:

Typical code without redux-thunk-routine

Looking at the example, we could find there is smell of boilerplate:

For every thunk:

  1. We have to define 3 constants: REQUEST, SUCCESS, FAILURE
  2. We have to define 3 action creators: request, success, failure
  3. We have same logic flow of dispatching actions

What if I tell you that there is a smart thing called routine to reduce these repetitive work?

Let’s have a look at the routine version of the previous example:

Rewrite using redux-thunk-routine

See, there is no need to define constants and synchronous action creators:

Each routine has 3 defined action types:

  • routine.REQUEST
  • routine.SUCCESS
  • routine.FAILURE

Each routine has 3 defined action creators (their types are also defined clearly):

  • routine.request()
  • routine.success()
  • routine.failure()

Further Discussion

Remove boilerplate from the thunk action creator

Instead of dispatching 3 actions in every thunk manually as shown above, we can replace it like below:

The actual flow is the same, but we write much less code.

If you want to overwrite the process of generating payload for request action and failure action, you can use the 3rd parameter:

Typing for reducer

By using redux-thunk-routine, the type of payloads are already checked when dispatching, so it is safe to put Action<any> when define the reducer:

However, if you still want to strictly add type of actions to reducer signiture, you can refer the code below:

Get typed payload in reducer

To access typed payload inside the reducer, you can use these functions:

  • routine.isSuccessAction()
  • routine.isFailureAction()
  • routine.getSuccessPayload()
  • routine.getFailurePayload()

Example:

How to use getState with getThunkActionCreator?

Well, there is a debate of using getState in action creators and it was indexed in this blog.

IMO, it is better to let the component to select all required states before dispatching a thunk. Because the flow and logic of thunk looks simpler in this way and it is easier to test.

According to that, there is no getState paramater passed to the executor function when using getThunkActionCreator.

However, if you need to call getState in some cases, you can do it by defining another thunk action creator to dispatch the thunk created by routine:

Other benefits of using routines

When using routine, we are enforced to follow a common pattern to name our action types. This gives us a huge advantage if we want to pull out more repetitive logic in reducers.

For example, we can implement a global loading reducer and a global error reducer based on regular expression to match action types, then remove the branches of dealing “REQUEST” and “FAILURE” actions in other reducers.

There are more details in this blog.

--

--

Thor Chen

Passionate JavaScript/TypeScript Developer with a Full-stack Background