You Aren’t Using Redux with Observables Enough
This article is a follow on from ‘you aren’t using Redux middleware enough’ . If you haven’t read it, you should. Because I wrote it.
Observables, mainly RxJS, have been becoming popular in JavaScript. For those who haven’t used observables, I find a good analogy to them is node’s event emitter crossed with JavaScript’s Array methods, such as map
and filter
.
A little known fact is that your Redux store is in fact an observable. The values it emits are the state of the store. For example,
Rx.Observable.from(store).subscribe(state => {
console.log(state)
})
In the last post, we looked at a music player that would use a isPlaying
parameter in the store to call play
and pause
when this value changed.
Using the map
and distinctUntilChanged
functions in RxJS, we can make an observable that emits values only when isPlaying
changes, and we can switch over the value to play or pause.
You can play around with this example on stack-blitz! Just remember to open your console.
CSS Color Search
Lets pretend we have a service that streams CSS color names, and it’s slow. We want to make an app that lets us search these color names. The searching should be asynchronous, but also, the search should be interruptible.
We’ll simulate the slow service an observable.
We now need a store that contains the search
and results
in the state.
Note that when we set the search, we clear the results.
Next we need an app for this. Just for a demo, we’ll use this.
Like in the previous example, we’re only interested in one part of the store, search
, and we’re also only interested when it changes. We can start with the same code.
We now need to combine this with our search service, getColorsObservable
. RxJS lets us combine these two with switchMap
. It’s similar to the map
function, except that you return an observable. The result is the flattened values of the returned observables.
The important part about switchMap
is that when a new value comes through from the input and we return a new observable, the currently running observable is cancelled, and no further values can be emitted. This means we don’t have to keep track of what is and isn’t running — it’s handled for us.
This code is also available on stack-blitz. If you wanted a challenge, see if you can get it to show a spinner when a search is in progress.
Closing Words
There’s a tonne of features in RxJS that can definitely make complicated store interactions easier. Using the built-in functions, you’re able to abstract away a lot of complexity and hidden state and make it harder to introduce bugs. We’ve barely scratched the surface of what you can do with observables, but hopefully I showed how they can be used with Redux.
Compared to the middleware approach, I tend to find it easier and simpler. You do only get access to the state, and not actions, which means you can’t handle every use case with it, but there is also nothing stopping you from using both middleware and observables at the same time!