[Redux] Async in Redux: redux-thunk

In most production web applications, data come from remote services. So you cannot get the data right away. There are a couple of ways to handle async operations in Redux, such as “redux-saga,” “redux-promise,” etc. But the “redux-thunk” is simple and effective for most scenarios.

Bad Code

// Action Creator
import axios from "axios";

export const fetchPosts = async () => {
  const response = await axios.create({
    baseURL: 'https://mydata.com'  
  }).get('/data');

  return {
    type: 'FETCH_DATA',
    payload: response
  }
}

If you run the code, you will get an error: Actions must be plain objects. What’s wrong with this code?

  • The “async – await” syntax does not return a plain object behind the scenes.
  • When we remove the “async – await“: When the action gets to a reducer, the fetched data is not available yet.

To solve this issue, we can use middleware to handle the async request.

  • Synchronous Action Creator: returns an action object instantly
  • Asynchronous Action Creator: Used when it takes some time to get the data (mostly through a network)

redux-thunk

A thunk is a computer science term. It is a function that wraps an expression to delay its evaluation.

The “redux-thunk” package allows you to write action creators (functions to create actions) that return a function instead of an action, and then you can execute the dispatch() later.

Setting up Thunk

“redux-thunk” is a middleware in Redux.

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

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

Structure of redux-thunk

The main idea of the redux-thunk is that you can return a function in action creators. This inner function can have 2 parameters (dispatch and getState) that are from the Redux store.

const action1 = (data) => {
  return {
    type: 'myAction',
    payload: data
  };
};

const asyncAction1 = () => {
  return (dispatch, getState) => {
    dispatch(...);
  };
}

Async Operation with Thunk

The most common usage of the “redux-thunk” is async actions.

const asyncLoad = () => {
  return (dispatch) => {
    return apis.loadData().then( data =>
      dispatch({
        type: 'load',
        payload: data
      });
    )).catch(error => { ... });
  };
}

Or you can use async-awit syntax.

const asyncLoad = () => {
  return asynch (dispatch, getState) => {
    const response = await apis.get('/data');

    dispatch({
      type: 'load',
      payload: response
    });
  };
}

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s