Simple Redux Thunk Example

Redux-thunk gives us the ability to call async methods inside one of our Redux actions. For example, imagine we needed to call an API and use the response data to update Redux state. Instead of doing the API call in our component, we can just add redux-thunk as middlewhere to our store and add another action which calls the API and then calls our normal Redux actions to update the Redux state. This is useful if for example we wanted to call a different dispatch action based on if the API returns successful or fails.

The first step is to add redux-thunk to the store. I am using TS so the implementation is as follows:

// INSIDE STORE INDEX FILE

import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';

import reducer from '../reducers/indexReducers';

export const store = createStore(
  reducer,
  composeWithDevTools(applyMiddleware(...[thunk]))  
);

Below shows 2 normal Redux actions and then a redux-thunk action

// REDUX ACTIONS FILE

import axios from "axios";

export const updateForm:Function = (step:string, name:string, payload:string) => {
  return { type: "UPDATE-FORM", step, name, payload};
}

export const updateFormError:Function = payload:string => {
  return { type: "UPDATE-FORM-ERROR", payload };
}

// Example Thunk
export const updateFormFromApi:Function = (step:string, name:string) => {
  return async (dispatch) => {
      try {
        const res:any = await axios.get('https://jsonplaceholder.typicode.com/todos/2');
        console.log(res);
        dispatch(updateForm(step, name, res.data.title));
      }
      catch (err) {
        dispatch(updateFormError("Some error message"));
      }
  }
}

This can then be called like this in our React component using react-redux (v7+ for the useSelector and dispatch hooks)

// INSIDE REACT COMPONENT

import { useSelector, useDispatch } from 'react-redux';
import { actions } from '../actions/indexActions';

const dispatch = useDispatch();

// Then in the return template
<button type="button"> {dispatch(actions.updateFormFromApi('step1', 'firstName'))}}>Click me</button>