Redux Ajax best practices

Using Ajax to communicate with the backend is common by modern JavaScript applications. Despite it being a basic functionality, it is listed as advanced topic in the official Redux introduction guide.

Ajax doesn’t come out-of-the-box with Redux, but instead you need a middleware. There is a wide selection of middlewares you can use and they all work in fundamentally different ways.

When you are starting out it can be very overwhelming with so many different technologies to choose from.

This guide will help you select the Redux Ajax middleware that suits your needs. The three most widely used and stable Redux Ajax middleware are:

  1. Redux Promise Middleware
  2. Redux Thunk Middleware
  3. Redux Saga Middleware

They are all viable options for your application depending on your specific needs. Let’s go through them all, but first…

A reminder on how action creators works

First let’s remind us how a classic, synchronous, action creator looks like:

function getUserName(userId) {
    return {
        type: "SET_USERNAME",
        userName: "a hardcoded user name"
    }
}

It’s a function that returns an object with a required type field which is the “name” of the action. It also has additional fields for data.

1. Redux Promise Middleware

This is the most simple way of doing Ajax calls with Redux.

When using Redux Promise, your action creator can return a Promise inside the Action.

function getUserName(userId) {
    return {
        type: "SET_USERNAME",
        payload: fetch(`/api/personalDetails/${userId}`)
                .then(response => response.json())
                .then(json =>  json.userName)
    }
}

Note that the promise must be under payload key in the action.

This middleware automatically dispatches two events when the Ajax call succeeds: SET_USERNAME_PENDING  and SET_USERNAME_FULFILLED . If something fails it dispatches SET_USERNAME_REJECTED .

When to use

  • You want the simplest thing with minimum overhead
  • You prefer convention over configuration
  • You have simple Ajax requirements

2. Redux Thunk Middleware

This is the standard way of doing Ajax with Redux.

When using Redux Thunk, your action creators returns a function that takes one argument dispatch:

function getUserName(userId) {
    return dispatch => {
        return fetch(`/api/personalDetails/${userId}`)
        .then(response => response.json())
        .then(json => dispatch({ type: "SET_USERNAME", userName: json.userName })
    }
}

dispatch  is a function that dispatches an action. The action creator can call dispatch inside .then to execute it asynchronously. The action creator can call dispatch as many time as it wants.

When to use

  • You make many Ajax calls in one action, and need to dispatch many actions
  • You require full control of the format of your actions

3. Redux Saga Middleware

This is the most advanced way of doing Ajax with Redux. It uses an ES6 feature called generators.

When using Redux Saga you do your Ajax calls in a saga instead of an action creator. This is how a saga looks like:

import { call, put, takeEvery } from 'redux-saga/effects'

// call getUserName when action SET_USERNAME is dispatched
function* mySaga() {
  yield takeEvery("SET_USERNAME", getUserName);
}

function* getUserName(action) {
   try {
      const user = yield call(fetch, `/api/personalDetails/${userId}`);
      yield put({type: "SET_USERNAME_SUCCEEDED", user: user});
   } catch (e) {
      yield put({type: "SET_USERNAME_FAILED", message: e.message});
   }
}

export default mySaga

Your sagas listen to actions which you dispatch as regular synchronous actions. In this case, the saga getUserName is executed when the action SET_USERNAME is dispatched.

The * next to the function means it’s a generator and yield is a generator keyword.

When to use

  • You need to be able to test the asynchronous flow easily
  • You are comfortable working with ES6 Generators
  • You value pure functions

Conclusion

There are many different middleware to choose from. My suggestion is that you after reading this guide pick one and start using that in your application today. Ajax is listed under the advanced topic in the docs but doesn’t let that discourage you. It is definitely something you can start working with even though you feel you are not an “advanced” Redux developer!