The Simplest Guide to Understand Redux-Thunk

Eze Sunday Eze
4 min readMar 16, 2019
Credit: Redux-Thunk Kunfu

Disclosure: Your should already be familiar with React and Redux to get the best of this tutorial. If you are looking to get started with redux please see Ohans Emmanuel’s guide to understanding redux.

Is Reactjs the best UI library for building UI components?

Ahhh, I don’t want to start that argument right now, though. :)

You know, I might agree or not. However, right now, react is amazing. So let’s get to business.

Redux-Think. Ohh, my bad, Redux Thunk. I assume you’ve heard about it and most likely have been having a hard time trying to tie the nuts.

According to the creators:

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.

Again, according to the Author:

Redux thunk middle-ware enables you to extend your store’s abilities, and let you write async logic that interacts with the store. Thunks are the recommended middleware for basic Redux side effects logic, including complex synchronous logic that needs access to the store, and simple async logic like AJAX requests.

In a nutshell, redux-thunk enables you to write asynchronous logic that interacts with the redux store.

You know when you are trying to run a blocking task like an ajax request, it takes time. So you need to wait for that task to be completed before dispatching an action, right?

Theoretically, Redux-Thunk middleware wraps around your function, goes ahead of you, runs the task until it’s completed, then it returns the result and allows your function to dispatch the action.

So, let’s get started with the practicals.

Create a ReactJS application with create-react-app

npx create-react-app my-app

In your index.js file

//default importimport React from "react";import ReactDOM from "react-dom";import "./index.css";import App from "./components/App/index";
// necessary imports for redux and thunkimport {createStore, applyMiddleware} from "redux";import {Provider} from "react-redux"import thunk from "redux-thunk";import {reducer} from "./store/reducers/reducers"const store = createStore(reducer, applyMiddleware(thunk))ReactDOM.render(<Provider store={store}><App /></Provider>,document.getElementById("root"));

Set up your regular Redux boilerplate code for your application and additionally import applyMiddleware from redux module.

import {createStore, applyMiddleware} from "redux";

Install redux-thunk:

$ npm install  — save redux-thunk 

Then let your store know that you want to use redux-thunk middleware. Pass thunk as an argument to applyMiddleware.

const store = createStore(reducer, applyMiddleware(thunk))

Simple, right. That’s it. Your store is now aware of your challenge. It’ll leverage thunk to fix it for you when there is need for it.

We are going to fetch some products from an API and display it on on our application.

Let’s make an ajax request to pull the products from the API. We’ll do this in our actions.js file.

actions.js

const getSoupDataFromAPIAsync=(products)=>{return {type:"get_products", payload:products}}export const loading = ()=>{   return {type:"isLoading", payload:true}}export const getSoupDataFromAPI=()=>{   return (dispatch)=>{     dispatch(loading())     fetch("http://shopsoup.herokuapp.com/api/v1/product")     .then((data)=>{     return data.json()   }).then((products)=>{dispatch(getSoupDataFromAPIAsync(products))})}}

First of all, we create an action creator function that dispatches our action when the ajax request is completed.

const getSoupDataFromAPIAsync=(products)=>{return {type:"get_products", payload:products}}

Secondly, we create a function that returns a function which will dispatch our action.

let’s use setTimeout to simulate an ajax request first.

export const getSoupDataFromAPI=()=>{
return (dispatch)=>{ dispatch(loading()) setTimeout(()=>{ console.log("success")
dispatch(success())
}, 5000)})

The function actually takes in two parameters, dispatch and getState. But right now we’re interested in the dispatch parameter which is also a function.

Remember, before the ajax request starts, our loading action will be dispatched and then when the request is completed, we also dispatch the action that sends our data to the store — assuming the setTimeout function is a XHR request.

Yea, that was for simplicity. Here is an actual XHR request dispatching an action.

export const getSoupDataFromAPI=()=>{    return (dispatch)=>{        dispatch(loading())       fetch("http://shopsoup.herokuapp.com/api/v1/product")        .then((data)=>{       return data.json()   }).then((products)=>{    dispatch(getSoupDataFromAPIAsync(products))})

Are you getting the point?

So here is our reducer:

const initialState = {products:[]}export const reducer=(state=initialState, action)=>{     const newState = {          ...state        }switch(action.type){   case "get_products":       return {         loading:false,         products:action.payload,          };   case "loading":       return {       loading:true       }   }return newState;}

That’s actually all there is to it.

And here is how you actually dispatch the action in your component depending on the action the user perform.

In our case we just call it in the componentDIdMount function as we want it to show when the component mounts.

 this.props.dispatch(actionCreators.getSoupDataFromAPI())

Here is our app.js file

Here is what it looks like:

Sample

You can find the entire code on Github.

Did you find this article interesting?

--

--