Introduce redux-thunk-routine: Less boilerplate code and better static typing with redux-thunk
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:
Looking at the example, we could find there is smell of boilerplate:
For every thunk
:
- We have to define 3 constants:
REQUEST
,SUCCESS
,FAILURE
- We have to define 3 action creators:
request
,success
,failure
- 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:
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.