Dispatching Async Actions with Redux
Tags: react, redux, webdev, javascript
Published: 2021-01-25 01:48:05

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


With Redux, we can use it to store data in a central location in our JavaScript app. It can work alone and it’s also a popular state management solution for React apps when combined with React-Redux.

In this article, we’ll look at how to dispatch actions asynchronously.

### Async Actions

In JavaScript, a lot of things have to be done asynchronously to avoid blocking the main execution thread.

Redux can dispatch asynchronous actions so that we don’t always have to change states synchronously.

To do this, we use the Redux-Thunk middleware. We can apply middlewares by using Redux’s `applyMiddleware` function.

With that, we can pass in functions that call `dispatch` instead of plain objects. We need this capability to run async actions that call `dispatch` and populate the store with it.

We can do this as follows:

```
import { createStore, applyMiddleware } from "redux";
import thunkMiddleware from "redux-thunk";

function jokeReducer(state = {}, action) {
  switch (action.type) {
    case "SET_JOKE":
      return action.joke;
    default:
      return state;
  }
}

let store = createStore(jokeReducer, applyMiddleware(thunkMiddleware));

function fetchJoke() {
  return async dispatch => {
    const response = await fetch("[https://api.icndb.com/jokes/random](https://api.icndb.com/jokes/random)");
    const joke = await response.json();
    dispatch({ type: "SET_JOKE", joke });
  };
}

(async () => {
  await store.dispatch(fetchJoke());
  console.log(store.getState().value.joke);
})();
```

In the code above, we have the `jokeReducer` which is the same as what we have before.

Then in to create the store, we write:

```
let store = createStore(jokeReducer, applyMiddleware(thunkMiddleware));
```

The difference from stores that only take plain object actions is that we have the `applyMiddleware` function where we passed in the `thunkMiddleware`.

The `thunkMiddleware` lets us pass in functions to dispatch instead of a plain object without it.

In the function we pass in, we can call `dispatch` with plain objects to do the synchronous actions.

Then we defined the `fetchJoke` function, which is or action creator, as follows:

```
function fetchJoke() {
  return async dispatch => {
    const response = await fetch("[https://api.icndb.com/jokes/random](https://api.icndb.com/jokes/random)");
    const joke = await response.json();
    dispatch({ type: "SET_JOKE", joke });
  };
}
```

In this function, we returned an async function that has the Redux `dispatch` function as the parameter.

Then once we get the joke with the Fetch API, we call `dispatch` provided in the parameter.

This way the Thunk middleware can call `dispatch` in the returned function.

We can return any function, but we need to use thunks for async functions since they don’t return plain objects.

Ordinary action creators must return plain objects, but if we use the Redux Thunk middleware, we can return a function that calls `dispatch` and `getState`.

Then we dispatch our async action and get the value from it as follows:

```
(async () => {
  await store.dispatch(fetchJoke());
  console.log(store.getState().value.joke);
})();
```

All we did above was call `dispatch` with the promise that the `fetchJoke` function returned as we defined above. Then we use `store.getState().value.joke` to get the joke’s value from the store.

![](https://cdn-images-1.medium.com/max/800/0*Wp42Wf-cEaM7-87s)Photo by [Sincerely Media](https://unsplash.com/@sincerelymedia?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

### Checking State Before Dispatching Synchronous Actions in Our Async Action Creator

We can write a function to check the state before getting data. To do this, we can make the following changes while keeping everything else the same:

```
function shouldFetchJoke(state) {
  return !state.value || !state.value.joke;
}

function fetchJoke() {
  return async (dispatch, getState) => {
    if (shouldFetchJoke(getState())) {
      const response = await fetch("[https://api.icndb.com/jokes/random](https://api.icndb.com/jokes/random)");
      const joke = await response.json();
      dispatch({ type: "SET_JOKE", joke });
    }
  };
}
```

In the code above, we defined the `shouldFetchJoke` function which checks the `state.value` and `state.value.joke` to see if the value has been set.

Then we change `fetchJoke` to call `shouldFetchJoke` . Then we take advantage of the `getState` parameter to get the state and check if a joke already exists in the store with `shouldFetchJoke` .

If not, then we proceed to get the joke.

### Conclusion

With the Redux Thunk middleware, we can pass in actions that aren’t plain objects to `dispatch`.

To use it, we have to call `applyMiddleware` with the `thunkMiddleware` as the argument.

Then we can create an action creator that returns a function with the `dispatch` and `getState` functions as the first and second parameter respectively, then we can get the state with `getState` as usual.