Redux + RxJs: Observable Actions
Tags: javascript, react, redux, rxjs
Published: 2019-07-09 19:03:02

---
title: Redux + RxJs: Observable Actions
published: true
description: Handle observable actions with Redux and RxJs.
tags: javascript, react, redux, rxjs
---

[RxJs](https://rxjs-dev.firebaseapp.com/) is one of my favorite Javascript libraries. It's almost an update to the language itself. In a recent role, we built an awesome data pipeline that handled sorting, filtering, aggregating and paginating for multiple large datasets in the user's device using RxJs. We also used a [Redux](https://redux.js.org/) store to maintain the application's state and [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) to store the large datasets in the user's device. With this and a few other tricks we were able to deliver a progressive web application that worked offline.

In this posts, I'd like to share with you a custom Redux middleware function that we developed to easily handle [Observables](http://reactivex.io/documentation/observable.html) within Redux actions. There are a few libraries in [NPM](https://www.npmjs.com/) that advertise the ability to do this but we found that the solution was simple enough that a security audit of a third-party library was just a waste of time. 

We wanted to keep our [React](https://reactjs.org/) view layer pure by keeping all business logic out of it. The application rendered the state of the Redux store which included the query necessary to extract the visible records from IndexedDB. Any actions from the user where mapped to a dispatch to the store which could be a simple action or an observable action. We skipped accepting functions as a thunk action since this is basically the same thing as an observable action but the middleware actually ignores these as well so it's safe to combine with [Redux-Thunk](https://github.com/reduxjs/redux-thunk).

We determined that there existed two types of logic that we wanted to store in observables.
- Business
- Asynchronous

That's really what RxJs is all about. Rather than have complex or several middlewares, intermediate actions and complex reducers to handle network requests and other business tasks, we delegated all of this to RxJs which allows us to isolate logic and compose it seamlessly. The Redux store focuses on mapping actions to state and notifying the React application of changes in state. With RxJs we can map a user dispatched action to a write to the Redux store all within a single observable interface which seamlessly hides away the asynchronous scheduling and the several intermediate tasks.

Ok, so enough talk. Here's a working example:

{% replit @EstebanHernande/LargeLuxuriousNumerators %}

The above is a simple script that uses a Redux store to add numbers together and return the total sum. It also keeps track of errors and has a loading flag so that the user wont receive intermediate values.

If you take a look at the `counterReducer`, we have four action types to keep in mind. The `_RESET` action type is emitted synchronously so the reducer will receive this notification before any of the notifications from the observable. This can be used to reset some state such as clearing the errors, clearing the counter, and setting the loading flat to `true`.

The `observerMiddleware` will handle observable actions.

By default, an Observable will attempt to execute synchronously and switch to asynchronous processing once it encounters a Promise or any other type of asynchronous operation. This might lead to the `_NEXT`, `_ERROR` and `_COMPLETE` notifications being emitted before the `_RESET` which might cause the `_RESET` notification to clear out the state after we've updated it. We need to change the default [scheduler](http://reactivex.io/documentation/scheduler.html) on the Observable to prevent this. Luckily for us, RxJs provides a very simple way to guarantee that an observable is processed asynchronously. All we have to do is apply the `observeOn` [operator](http://reactivex.io/documentation/operators.html) with the `asapScheduler` to the observable and presto!

Now, our observable will begin processing after the `_RESET` notification and will emit every value as a `_NEXT` notification. Our reducer will update the state of the counter for each of these notifications.

Finally, if the observable emits an `_ERROR` notification, our reducer will update the state with the error. Otherwise, the observable will emit a `_COMPLETE` notification which our reducer will process to set the loading flag to `false`. Now our user-facing application can remove the loading indicator and display the total sum (or the error message).

We'll test this out by creating an action generator named `addNumbers` that receives any amount of numbers as arguments and dispatches an action with an observable payload that emits these numbers in sequence before completing. Given the numbers 1 through 4, we expect a sum of 10. If we run the above script, we can see that once the loading flat is set to `false` and the value of `counter` will be set informing us that the process has finished loading and the total sum is `10`.