Front-End Insights

Redux Thunk – how to populate various reducers

ProgrammingReduxTutorial

Recently, in my current front-end project, I was faced with this problem: I have an edit form which is split into five steps, and each step has its own reducer – but… I have only one REST endpoint so I have to populate them all at once. I tried different approaches (e.g. redux middleware which was detecting the action type and was doing the job then) but all of them were awful. But then, I discovered redux thunk and today I will show you how I utilised it to solve my problem!

What is Redux Thunk?

As stated on the official github page of the project:

Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.

Sounds great, right? We get dispatch and getState functions inside the action creator – it could be very useful…

But first, let’s see how to configure it. Redux Thunk is nothing but redux middleware, so we have to just pass it as a parameter of the applyMiddleware function while creating the redux store, just like below:

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';

const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

Great, so let’s see how I used these capabilities to solve my issue.

Using Redux Thunk to populate other reducers’ states

Ok, so if we have the dispatch function available in the action creator we can use it to dispatch other actions. Let’s imagine that we have several sample action creators:

// stepOneActions.js
export const POPULATE_STEP_ONE = 'POPULATE_STEP_ONE';

export function populateStepOne(data) {
  return {
    type: 'POPULATE_STEP_ONE',
    payload: data
  };
} 

// stepTwoActions.js
export const POPULATE_STEP_TWO = 'POPULATE_STEP_TWO';

export function populateStepTwo(data) {
  return {
    type: 'POPULATE_STEP_TWO',
    payload: data
  };
} 

Nothing special right? Ok so now we have a third action creator which gets data from the REST API:

// allStepsActions.js
export const GET_STEPS_START = 'GET_STEPS_START';
export const GET_STEPS_SUCCESS = 'GET_STEPS_SUCCESS';
export const GET_STEPS_ERROR = 'GET_STEPS_ERROR';

export function getSteps() {
  return ({ fetch, dispatch }) => ({
    type: 'GET_STEPS',
    payload: {
      promise: fetch('/steps/get').then(response => {
        // we got data so we can populate other reducers
        dispatch(populateStepOne(response.stepOne));
        dispatch(populateStepTwo(response.stepTwo));        
      })
    }
  });
}

Ok, let’s see what is going on here… We have a getSteps action which gets data for the whole edit form (which is split into two steps in this example). As you can see, we have the dispatch function available (I’ve also injected the fetch method to call the REST API – I will omit the explanation as it is a subject for another blog post) – we can now just dispatch other actions which will use fetched data to populate reducers holding particular steps.

Problem solved! 😉

Summary

As you can see, the Redux Thunk middleware could be very useful. If you can dispatch actions inside other actions, you can control your application flow in a very efficient way.

I wonder what you think about my solution – is there any better approach to solve my problem?