How to Scale a Redux Application with Redux-Action-Recompose

ryan yan
3 min readFeb 25, 2017

--

One of biggest challenges that you may face with a Redux application is having to write duplicated action-creators and reducers for common actions, such as data fetching. There is a partial solution proposed in the Redux Documentation for reusing reducers. However, you will realize that you still have to write duplicated action-creators or complicated action-creators.

You will experience similar problems if you want to use a shared component at different places. For instance, if you have a generic datatable component, which allows sorting, row selection, data fetching, pagination, etc.

shared datatable component with sorting, row selection, data fetching

However, if you want to use the datatable in multiple places, you will realize that you have to repeat the action-creators and reducers.

This article will introduce redux-action-recompose and explain how it will help you to scale your application by assisting you to reuse common action-creators and reducers. The article will use an fetch data example to illustrate how redux-action-recompose work.

Suppose you need to write an application with two components, users and todos. Both component will need to fetch and display fetched data. You might write your async action-creators (fetchData) and reducers (asyncHandlers) as follows: (example follows The Ducks File Structure):

Async Action Creators (fetchData) and Reducers (asyncHandlers)

In an ideal world, both users and todos would simply need to import and use the async action-creators and reducers as something like these:

import and use shared action-creators in an ideal world
import to use shared reducers in an ideal world

However, this will not work. When either users or todos calls fetchData(…), the async reducer would be fired for both components, because they would be using the same action {type: ‘FETCH_DATA_REQUEST’} and {type: ‘FETCH_DATA_RESPONSE’, …}. Therefore, both users and todos have to implement their own version of the action-creators and reducers with different action types, and you will end up with many duplicated action-creators and reducers.

Redux-Action-Recompose is an npm package that will solve this problem for you. Redux-Action-Recompose exposes two functions, ‘decorateHandlers’ and ‘decorateActions’. You will simply use these two functions to decorate your action-creators and reducers with unique labels for the users and todos.

For instance, to use the shared action-creators and reducers in the users component. You simply need to decorate the asyncActions and asyncHandlers with a label ‘users’.

import and use shared action-creators using redux-action-recompose
import and use shared reducers using redux-action-recompose

Now, all of the action types in the action-creators and reducers are namespaced. For instance, when this.props.fetchData(…) is called in users component, it will dispatch {type: ‘users/FETCH_DATA_REQUEST’} and {type: ‘users/FETCH_DATA_RESPONSE’, …}, instead of the original {type: ‘FETCH_DATA_REQUEST’} and {type: ‘FETCH_DATA_RESPONSE’, …}. The users reducers will also be listening to the namespaced action types.

In your todos component, you will simply decorated the action-creators and reducers with a different label (i.e. ‘todos’). It will then get a unique version of the async action-creators and reducers by having a unique label.

In addition, another important advantage of Redux-Action-Recompose is that it will also allow you to easily overwrite and override your action-creators and reducers by using the spread operator. For instance,

decorateHandlers({…asyncHandlers, …additionalHandlers}, ‘todos’)

decorateActions({…asyncActions, …additionalActions}, dispatch, ‘todos’)

--

--