Async actions in Redux with RxJS and Redux Observable
Tags: react, redux, reduxobservable
Published: 2018-05-28 12:21:42

---
title: Async actions in Redux with RxJS and Redux Observable
published: true
description: An elegant way of handling asynchronous actions reactively in a Redux architecture
tags: react,redux,redux-observable
cover_image: https://i.imgur.com/epFvZTG.jpg
---
#Introduction

### What is Redux?
[*Redux*](https://redux.js.org/) is an amazing library. For those of you who don't know what Redux is, it is a **predictable state container** for JavaScript apps. In English, it acts as a single source of truth for your application's state. The state, or Redux *store*, as it is called, can only be altered by dispatching *actions*, which are handled by *reducers*, who dictate how the state should be modified depending on the type of action dispatched. For those of you who aren't familiar with Redux, check out [**this link**](https://medium.com/codingthesmartway-com-blog/learn-redux-introduction-to-state-management-with-react-b87bc570b12a).

Now, Redux is most commonly used in combination with React, although it's not bound to it - it can be used together with any other view library.

### Redux's issue
However, Redux has one, but very significant problem - it doesn't handle **asynchronous operations** very well by itself. On one side, that's bad, but on the other, Redux is just a library, there to provide state management for your application, just like React is only a view library. None of these constitute a complete framework, and you have to choose the tools you use for different things by yourself. Some view that as a bad thing since there's no one way of doing things, some, including me, view it as good, since you're not bound to any specific technology. And that's good, because everyone can choose the tech that they think fits the best to their needs.


### Handling asynchronous actions
Now, there are a couple of libraries which provide Redux middleware for handling asynchronous operations. When I first started working with React and Redux, the project that I was assigned to used [**Redux-Thunk**](https://github.com/reduxjs/redux-thunk). Redux-Thunk allows you to write action creators which return functions instead of plain objects (by default all actions in Redux must be plain objects), which in turn allow you to delay dispatching of certain actions.

And as a beginner in React/Redux back then, thunks were pretty awesome. They were easy to write and understand, and didn't require any additional functions - you were basically just writing action creators, just in a different way.

However, once you start to get into the workflow with React and Redux, you realize that, although very easy to use, thunks aren't quite that good, because, 1. You can end up in callback hell, especially when making API requests, 2. You either stuff your callbacks or your reducer with business logic for handling the data (because, let's be honest, you're not going to get the perfectly formatted data EVERY time, especially if you use third-party APIs), and 3. They're not really testable (you'd have to use spy methods to check whether dispatch has been called with the right object). So, I started to research for other possible solutions that would be a better fit. That's when I ran into [**Redux-Saga**](https://redux-saga.js.org/).

Redux Saga was very close to what I was looking for. From its website, *The mental model is that a saga is like a separate thread in your application that's solely responsible for side effects.* What that basically means is that *sagas* run separately from your main application and listen for dispatched actions - once the action that that particular saga is listening for is dispatched it executes some code which produces side effects, like an API call. It also allows you to dispatch other actions from within the sagas, and is easily testable, since sagas return *Effects* which are plain objects. Sounds great, right?

Redux-Saga DOES come with a tradeoff, and a big one for most devs - it utilizes Javascript's generator functions, which have a pretty steep learning curve. Now, props *(see what I did there, hehe)* to the Redux Saga creators for using this powerful feature of JS, however, I do feel that generator functions feel pretty unnatural to use, at least for me, and even though I know how they work and how to use them, I just couldn't get around to actually **using** them. *It's like that band or singer that you don't really have a problem listening to when they're played on the radio, but you would never even think about playing them on your own.* Which is why my search for the async-handling Redux middleware continued.

One more thing Redux-Saga doesn't handle very nicely is cancellation of already dispatched async actions - such as an API call (something Redux Observable does very nicely due to its reactive nature).

### The next step
A week or so ago, I was looking at an old Android project a friend and I had written for college and saw some RxJava code in there, and thought to myself: *what if there's a Reactive middleware for Redux?* So I did some research and, well, the gods heard my prayers: **Cue [Redux Observable](https://redux-observable.js.org/)**.

So what *is* Redux Observable? It is another middleware for Redux that lets you handle asynchronous data flow in a **functional, reactive and declarative** way. What does this mean? It means that you write code that works with asynchronous data streams. In other words, you basically listen for new values on those streams (*subscribe* to the streams*) and react to those values accordingly.

For the most in-depth guides on reactive programming in general, check out [this link](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754), and [this link](http://blog.danlew.net/2017/07/27/an-introduction-to-functional-reactive-programming/). Both give a very good overview on what (Functional) Reactive Programming is and give you a very good mental model.

### What problems does Redux Observable solve?
The most important question when looking at a new library/tool/framework is how it's going to help you in your work. In general, everything that Redux Observable does, Redux-Saga does as well. It moves your logic outside of your action creators, it does an excellent job at handling asynchronous operations, and is easily testable. However, **IN MY OPINION**, Redux Observable's entire workflow just feels more natural to work with, considering that both of these have a steep learning curve (both generators and reactive programming are a bit hard to grasp at first as they not only require learning but also adapting your mindset).

*From the Redux Observable official guide: The pattern of handling side effects this way is similar to the "process manager" pattern, sometimes called a "saga", but the original definition of saga is not truly applicable. If you're familiar with redux-saga, redux-observable is very similar. But because it uses RxJS it is much more declarative and you utilize and expand your existing RxJS abilities.*

### Can we start coding now?
So, now that you know what functional reactive programming is, and if you're like me, you really like how natural it feels to work with data. Time to apply this concept to your React/Redux applications.

First of all, as any Redux middleware, you have to add it to your Redux application when creating the store.

First, to install it, run
`npm install --save rxjs rxjs-compat redux-observable`
or
`yarn add rxjs rxjs-compat redux-observable`
depending on the tool that you're using.

Now, the basis of Redux Observable are **epics**. Epics are similar to sagas in Redux-Saga, the difference being that instead of waiting for an action to dispatch and delegating the action to a worker, then pausing execution until another action of the same type comes using the yield keyword, epics run separately and listen to a stream of actions, and then reacting when a specific action is received on the stream. The main component is the `ActionsObservable` in Redux-Observable which extends the `Observable` from RxJS. This observable represents a stream of actions, and every time you dispatch an action from your application it is added onto the stream.

Okay, let's start by creating our Redux store and adding Redux Observable middleware to it (small reminder, to bootstrap a React project you can use the `create-react-app` CLI). After we're sure that we have all the dependencies installed (`redux, react-redux, rxjs, rxjs-compat, redux-observable`), we can start by modifying our `index.js` file to look like this

```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

import { createStore, applyMiddleware } from 'redux';
import { createEpicMiddleware } from 'redux-observable';
import { Provider } from 'react-redux';

const epicMiddleware = createEpicMiddleware(rootEpic);

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

const appWithProvider = (
    <Provider store={store}>
        <App />
    </Provider>
);

ReactDOM.render(appWithProvider, document.getElementById('root'));
```

As you might have noticed, we're missing the `rootEpic` and `rootReducer`. Don't worry about this, we'll add them later. For now, let's take a look at what's going on here:

First of all, we're importing the necessary functions to create our store and apply our middleware. After that, we're using the `createEpicMiddleware` from Redux Observable to create our middleware, and pass it the root epic (which we'll get to in a moment). Then we create our store using the `createStore` function and pass it our root reducer and apply the epic middleware to the store.

Okay, now that we have everything set up, let's first create our root reducer. Create a new folder called `reducers`, and in it, a new file called `root.js`. Add the following code to it:

```javascript
const initialState = {
    whiskies: [], // for this example we'll make an app that fetches and lists whiskies
    isLoading: false,
    error: false
};

export default function rootReducer(state = initialState, action) {
    switch (action.type) {
        default:
            return state;
    }
}
```

Anyone familiar with Redux already knows what's going on here - we're creating a reducer function which takes `state` and `action` as parameters, and depending on the action type it returns a new state (since we don't have any actions defined yet, we just add the `default` block and return the unmodified state).

Now, go back to your `index.js` file and add the following import:
```javascript
import rootReducer from './reducers/root';
```

As you can see, now we don't have the error about `rootReducer` not existing. Now let's create our root epic; first, create a new folder `epics` and in it create a file called `index.js`. In it, add the following code for now:

```javascript
import { combineEpics } from 'redux-observable';

export const rootEpic = combineEpics();
```

Here we're just using the provided `combineEpics` function from Redux Observable to combine our (as of now, nonexistent) epics and assign that value to a constant which we export. We should probably fix our other error in the entry `index.js` file now by simply adding the following import:
```javascript
import { rootEpic } from './epics';
```

Great! Now that we handled all the configuration, we can go and define the types of actions that we can dispatch and also action creators for those whiskies.

To get started, create a new folder called actions and an `index.js` file inside.
(Note: for large, production-grade projects you should group your actions, reducers and epics in a logical way instead of putting it all in one file, however, it makes no sense here since our app is very small)

Before we start writing code, let's think about what types of actions we can dispatch. Normally, we would need an action to notify Redux/Redux-Observable that it should start fetching the whiskies, let's call that action FETCH_WHISKIES. Since this is an async action, we don't know when exactly it will finish, so we will want to dispatch a FETCH_WHISKIES_SUCCESS action whenever the call completes successfully. In similar manner, since this is an API call and it can fail we would like to notify our user with a message, hence we would dispatch a FETCH_WHISKIES_FAILURE action and handle it by showing an error message.

Let's define these actions (and their action creators) in code:
```javascript
export const FETCH_WHISKIES = 'FETCH_WHISKYS';
export const FETCH_WHISKIES_SUCCESS = 'FETCH_WHISKYS_SUCCESS';
export const FETCH_WHISKIES_FAILURE = 'FETCH_WHISKYS_FAILURE';

export const fetchWhiskies = () => ({
    type: FETCH_WHISKIES,
});

export const fetchWhiskiesSuccess = (whiskies) => ({
    type: FETCH_WHISKIES_SUCCESS,
    payload: whiskies
});

export const fetchWhiskiesFailure = (message) => ({
    type: FETCH_WHISKIES_FAILURE,
    payload: message
});
```

For anyone who is unclear about what I'm doing here, I'm simply defining constants for the action types and then using the lambda shorthand notation of ES6 I am creating arrow functions which return a plain object containing a type and (optional) payload property. The type is used to identify what kind of action has been dispatched and the payload is how you send data to the reducers (and the store) when dispatching actions (note: the second property doesn't have to be called payload, you can name it anything you want, I'm doing it this way simply because of consistency).

Now that we've created our actions and action creators, let's go and handle these actions in our reducer:
Update your `reducers/index.js` to the following.

```javascript
import {
    FETCH_WHISKIES,
    FETCH_WHISKIES_FAILURE,
    FETCH_WHISKIES_SUCCESS
} from '../actions';

const initialState = {
    whiskies: [],
    isLoading: false,
    error: null
};

export default function rootReducer(state = initialState, action) {
    switch (action.type) {
        case FETCH_WHISKIES:
            return {
                ...state,
                // whenever we want to fetch the whiskies, set isLoading to true to show a spinner
                isLoading: true,
                error: null
            };
        case FETCH_WHISKIES_SUCCESS:
            return {
                whiskies: [...action.payload],
                // whenever the fetching finishes, we stop showing the spinner and then show the data
                isLoading: false,
                error: null
            };
        case FETCH_WHISKIES_FAILURE:
            return {
                whiskies: [],
                isLoading: false,
                // same as FETCH_WHISKIES_SUCCESS, but instead of data we will show an error message
                error: action.payload
            };
        default:
            return state;
    }
}

```

Now that we've done all that, we can FINALLY write some Redux-Observable code (sorry for taking so long!)

Go to your `epics/index.js` file and let's create our first epic. To start off, you're going to need to add some imports:
```javascript
import { Observable } from 'rxjs';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/catch';
import { ajax } from 'rxjs/observable/dom/ajax';

import {
    FETCH_WHISKIES,
    fetchWhiskiesFailure,
    fetchWhiskiesSuccess
} from "../actions";
```

What we did here is import the action creators that we will need to dispatch as well as the action type that we will need to watch for in the action stream, and some operators from RxJS as well as the `Observable`. Note that neither RxJS nor Redux Observable import the operators automatically, therefore you have to import them by yourself (another option is to import the entire 'rxjs' module in your entry index.js, however I would not recommend this as it will give you large bundle sizes). Okay, let's go through these operators that we've imported and what they do:

`map` - similar to Javascript's native `Array.map()`, `map` executes a function over each item in the stream and returns a new stream/Observable with the mapped items.
`of` - creates an Observable/stream out of a non-Observable value (it can be a primitive, an object, a function, anything).
`ajax` - is the provided RxJS module for doing AJAX requests; we will use this to call the API.
`catch` - is used for catching any errors that may have occured
`switchMap` - is the most complicated of these. What it does is, it takes a function which returns an Observable, and every time this inner Observable emits a value, it merges that value to the outer Observable (the one upon which switchMap is called). Here's the catch tho, every time a new inner Observable is created, the outer Observable subscribes to it (i.e listens for values and merges them to itself), and cancels all other subscriptions to the previously emitted Observables. This is useful for situations where we don't care whether the previous results have succeeded or have been cancelled. For example, when we dispatch multiple actions for fetching the whiskies we only want the latest result, switchMap does exactly that, it will subscribe to the latest result and merge it to the outer Observable and discard the previous requests if they still haven't completed. When creating POST requests you usually care about whether the previous request has completed or not, and that's when mergeMap is used. `mergeMap` does the same except it doesn't unsubscribe from the previous Observables.

With that in mind, let's see how the Epic for fetching the whiskies will look like:

```javascript
const url = 'https://evening-citadel-85778.herokuapp.com/whiskey/'; // The API for the whiskies
/*
    The API returns the data in the following format:
    {
        "count": number,
        "next": "url to next page",
        "previous": "url to previous page",
        "results: array of whiskies
    }
    since we are only interested in the results array we will have to use map on our observable
 */

function fetchWhiskiesEpic(action$) { // action$ is a stream of actions
    // action$.ofType is the outer Observable
    return action$
        .ofType(FETCH_WHISKIES) // ofType(FETCH_WHISKIES) is just a simpler version of .filter(x => x.type === FETCH_WHISKIES)
        .switchMap(() => {
            // ajax calls from Observable return observables. This is how we generate the inner Observable
            return ajax
                .getJSON(url) // getJSON simply sends a GET request with Content-Type application/json
                .map(data => data.results) // get the data and extract only the results
                .map(whiskies => whiskies.map(whisky => ({
                    id: whisky.id,
                    title: whisky.title,
                    imageUrl: whisky.img_url
                })))// we need to iterate over the whiskies and get only the properties we need
                // filter out whiskies without image URLs (for convenience only)
                .map(whiskies => whiskies.filter(whisky => !!whisky.imageUrl))
            // at the end our inner Observable has a stream of an array of whisky objects which will be merged into the outer Observable
        })
        .map(whiskies => fetchWhiskiesSuccess(whiskies)) // map the resulting array to an action of type FETCH_WHISKIES_SUCCESS
        // every action that is contained in the stream returned from the epic is dispatched to Redux, this is why we map the actions to streams.
        // if an error occurs, create an Observable of the action to be dispatched on error. Unlike other operators, catch does not explicitly return an Observable.
        .catch(error => Observable.of(fetchWhiskiesFailure(error.message)))
}
    
```

After this, there's one more thing remaining, and that is to add our epic to the `combineEpics` function call, like this:

```javascript
export const rootEpic = combineEpics(fetchWhiskiesEpic);
```

Okay, there's a lot going on here, I'll give you that. But let's break it apart piece by piece.

`ajax.getJSON(url)` returns an Observable with the data from the request as a value in the stream.
`.map(data => data.results)` takes all values (in this case only 1) from the Observable, gets the `results` property from the response and returns a new Observable with the new value (i.e only the `results` array).
```javascript
.map(whiskies => whiskies.map(whisky => ({
                    id: whisky.id,
                    title: whisky.title,
                    imageUrl: whisky.img_url
                })))
```
takes the value from the previous observable (the results array), calls `Array.map()` on it, and maps each element of the array (each whisky) to create a new array of objects which only hold the id, title and imageUrl of each whisky, since we don't need anything else.

`.map(whiskies => whiskies.filter(whisky => !!whisky.imageUrl))` takes the array in the Observable and returns a new Observable with the filtered array.

The `switchMap` that wraps this code takes this Observable and merges the inner Observable's stream to the stream of the Observable that calls `switchMap`. If another request for the whiskies fetch came through, this operation would be repeated again and the previous result discarded, thanks to `switchMap`.

`.map(whiskies => fetchWhiskiesSuccess(whiskies))` simply takes this new value we added to the stream and maps it to an action of type FETCH_WHISKIES_SUCCESS which will be dispatched after the Observable is returned from the Epic.

`.catch(error => Observable.of(fetchWhiskiesFailure(error.message)))` catches any errors that might have happened and simply returns an Observable. This Observable is then propagated through switchMap which again merges it to the outer Observable and we get an action of type FETCH_WHISKIES_FAILURE in the stream.

Take your time with this, it is a complicated process which, if you haven't ever touched Reactive programming and RxJS, can look and sound very scary (read those links I provided above!).

After this, all we need to do is render a UI, which will have a button that dispatches the action and a table to show the data. Let's do that; start off by creating a new folder called components and a new component called Whisky.jsx.

```javascript
import React from 'react';

const Whisky = ({ whisky }) => (
    <div>
        <img style={{ width: '300px', height: '300px' }} src={whisky.imageUrl} />
        <h3>{whisky.title}</h3>
    </div>
);

export default Whisky;
```

This component simply renders a single whisky item, its image and title. (Please, *for the love of God*, never use inline styles. I'm doing them here because it's a simple example).

Now we want to render a grid of whisky elements. Let's create a new component called WhiskyGrid.jsx.

```javascript
import React from 'react';

import Whisky from './Whisky';

const WhiskyGrid = ({ whiskies }) => (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr' }}>
        {whiskies.map(whisky => (<Whisky key={whisky.id} whisky={whisky} />))}
    </div>
);

export default WhiskyGrid;
```

What WhiskyGrid does is it leverages CSS-Grid and creates a grid of 3 elements per row, simply takes the whiskies array which we will pass in as props and maps each whisky to a Whisky component.

Now let's take a look at our App.js:
```javascript
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import './App.css';

import { fetchWhiskies } from './actions';

import WhiskyGrid from './components/WhiskyGrid';

class App extends Component {
  render() {
    const {
      fetchWhiskies,
      isLoading,
      error,
      whiskies
    } = this.props;

    return (
      <div className="App">
        <button onClick={fetchWhiskies}>Fetch whiskies</button>
        {isLoading && <h1>Fetching data</h1>}
        {!isLoading && !error && <WhiskyGrid whiskies={whiskies} />}
        {error && <h1>{error}</h1>}
      </div>
    );
  }
}

const mapStateToProps = state => ({ ...state });

const mapDispatchToProps = dispatch =>
    bindActionCreators({
        fetchWhiskies
    }, dispatch);

export default connect(mapStateToProps, mapDispatchToProps)(App);
```

As you can see, there's lots of modifications here. First we have to bind the Redux store and action creators to the component's props. We use the `connect` HOC from react-redux to do so. After that, we create a div which has a button whose onClick is set to call the fetchWhiskies action creator, now bound to `dispatch`. Clicking the button will dispatch the FETCH_WHISKIES action and our Redux Observable epic will pick it up, thus calling the API. Next we have a condition where if the isLoading property is true in the Redux store (the FETCH_WHISKIES has been dispatched but has neither completed nor thrown an error) we show a text saying Load data. If the data is not loading and there is no error we render the `WhiskyGrid` component and pass the whiskies from Redux as a prop. If error is not null we render the error message.

###Conclusion

Going reactive is not easy. It presents a completely different programming paradigm and it forces you to think in a different manner. I will not say that functional is better than object-oriented or that going Reactive is the best. The best programming paradigm, **IN MY OPINION**, is a combination of paradigms. However, I do believe that Redux Observable does provide a great alternative to other async Redux middleware and after you pass the learning curve, you are gifted with an amazing, natural method of handling asynchronous events.

If you have any questions please ask in the comments! If this gets enough interest we can look into delaying and cancelling actions.

Cheers :)