DIY Redux with RxJS: Part 2

1,409 reads

@ onerizafer Öner Zafer Software engineer, senior frontend developer based in Berlin. Hard Sci-Fi addict.

Photo by Steve Halama on Unsplash

In case you didn’t read the part one I would recommend you to read it. The first part is covering how to implement the core functionalities of Redux.

At DIY Redux with RxJS => RxDx Part 2, I will reveal the internals of some most popular and widely used Redux middlewares. As I mentioned in the first part of the article -which you can find above-, my goal is to do an experiment to combine RxJS and all widely used Redux middlewares into a library which can be found here.

Before diving into the subject, it is always good to review the required signature of redux middlewares.

(storeAPI) => (next) => (action) => state

Before I start, I need to confess, when I finished the createStore function I thought with bold confidence that all available middlewares of redux will work for my version of it. Actually, it worked but not for most of them, not for widely used ones :( So I had to provide these libraries/middlewares by re-implementing them or at least implementing similar ones. Here, we go!

A different approach to redux-observable

Under normal conditions, Redux does not implement/has no intention to implement TC39 Observable therefore it is not compatible with RxJS by default.

Here I have to mention the use cases of observables; if you need to operate on streams of events, then it is probably better to use an observable. What kind of operations am I talking on? Merging two streams into one, filtering, mapping or redirecting a stream. For more technical detail check here.

When implementing a Redux store you will definitely notice that you have to create lots of actions. I have to admit that actions are pretty similar to events and on the runtime, they will be triggered hundreds of times. So this must be the point where redux-observable catches Redux as a streaming event source. By doing so, it creates a good opportunity for developers who are willing to create some asynchronous side effects on each selected action. For detailed documentation on redux-observable, you may check here. TL;DR The magic happens in a function called createEppicsMiddleware that has the signature below:

const createEpicsMiddleware = (rootEpic) => (storeAPI) => (next) => (action) => state

To be honest, when I checked the documentation, I didn’t like the way we need to consume this library. For me, the usage of Effect from NgRx is more classy :) So I decided not to mimic the API of redux-observable, yet the functionality should be there. So I ended up something as follows.

As I mentioned before I really like NgRx style usage and I borrowed Effect decorator and ofType tappable function.

Effect decorator is as simple as adding a type on the original variable. And if your environment supports experimental decorators the usage can be as follows:

@Effect()

const someCoolAsyncSideEffect = action$

.pipe(ofType('SomeCoolAction', 'OrEvenCoolerAction'))

.pipe(map(() => {type: 'SomeOtherCoolAction'}));

Unfortunately, if your environment does not support experimental decorators this code piece won’t look that much handsome.

Reselect

While I was implementing the createStore function in the first part of this story, I implemented a select function in the exposed store object by trusting my gut feeling. This decision revealed itself as pretty useful in implementing the reselect library of RxDx. To be frank, reselect is completely compatible with RxDx, yet I was experimenting and I needed to challenge myself to combine all libraries into it.

What does reselect do? It takes the state or a state portion and returns a portion of it. So what’s the deal? We can achieve the same functionality without it like the example below:

const reselect = (state, key) => state[key];

The example above totally undermines the power of this simple yet incredibly useful library. The deal is, the reselect provides a simple repeatable function which has memoization inside to speed up our -possibly complex- filtering on states.

This function will have a key functionality while we are consuming the RxDx store in react components. The usage of a selector as simple as follows:

Redux Dev Tools Middleware

I thought that the absence of the integration to redux dev tools would be a big missing part of RxDx. Then I started reading the API documentation of dev tools and I found what I need __REDUX_DEVTOOLS_EXTENSION__.connect

After this point, it was super easy to combine everything into a middleware:

Finally, I reached a point which I can create a store, add some reducers, apply built-in optional middlewares and select a specific state child with memoization:

Final words until next time

I strongly recommend such experiments for anybody who wants to learn more about any library or any kind of design patterns or coding styles. It will cause you to question lots of things you do during normal daily coding tasks of yours.

Next time I will continue my experiment with how to combine a redux-like-library with react components and it will include lots of information about HOCs and decorators.

If you are also a self-learner like me and a little bit impatient on top of it, let’s just try it yourself until I release the 3rd and the last part of the RxDx article.

Here is my repo to start your own experiment:

If you are interested in RxDx and enjoyed the article so far, please don’t forget hitting the clap (you can clap up to 50 times). If you share your ideas and feedback below, I would only be glad!

Thanks for reading!

Part 3:

Share this story @ onerizafer Öner Zafer Read my stories Software engineer, senior frontend developer based in Berlin. Hard Sci-Fi addict.

Tags