DIY Redux with RxJS: Part 3 – Hacker Noon

In this part, I will create a HOC (Higher Order Component) to connect RxDx with React.Component. I assume that you already know about React.Component, so that I won’t be explaining it again. But I need to explain HOCs which is the heart of what I will demonstrate below.

What the heck are these Higher-Order Components?

Basically, HOC is a class decorator. But what is a class decorator? Sometimes while we are coding we start feeling that all classes we create have the same basic properties. At that point, we realize that we are repeating ourselves which is completely against the DRY rule. So we start trying to find a way to isolate the repeating parts. Or while we are coding we need to add a feature to our classes without changing the implementation of it. In both cases, our purpose is to achieve code sharing between classes. So the very best answer to our problem described above is kind of a class factory function.

Class factory functions are functions which returns a class. (welcome to the weirdness of the javascript world).

// the most primitive description of a class factory function
function giveMeClass(someArguments) {
return class SomeDynamicallyGeneratedClass {}
}

The primitive class factory function is not a class decorator yet. To be a class decorator, a class factory function requires a class as an argument and the returning/produced class will be an extended version of the input class:

//enhance decorator
function ehance(targetClass) {
return class EnhancedClass extends targetClass {
constructor() {
this.isEnhanced = true;
}
}
//usage in enviroment where experimental decorators allowed
@enhace
class Normal {}
console.log(new Normal().isEnhanced) // true
//usage in enviroment where experimental decorators not allowed
class Normal {}
const Enhanced = enhance(Normal);
console.log(new Enhanced().isEnhanced) // true

As it’s mentioned before, HOCs are also decorators and works exactly the same way as a class decorator. A HOC takes a React component -which is a class- and returns another React component. For detailed documentation of HOCs you may follow the link below but if you are in the mood TL;DR I will continue with a summary of it:

Now it’s time to extend the decorator example above to make it a HOC by replacing class input and output with a React Component. I have to mention that using React component as input/output gives us a couple of opportunities, but I will continue with recommended one which is wrapping the original component with another:

// a primitive HOC which makes A component great nothing 🙂
function makeGreat(WrappedComponent) {
return class EnhancedComponent extends React.Component {
constructor() {
this.state = {isGreat: true}
}
      render() {
return <WrappedComponent {...this.props, ...this.state} />
}
}
}
// usage
class LameComponent extends React.Component {
render() {
return
{this.props.isGreat? 'Great': 'Lame'}

}
}
const GreatComponent = makeGreat(LameComponent);
<LameComponent /> // this will render 
Lame

<GreatComponent /> // this will render
Great
// alternative usage if experimental decorators are allowed
@makeGreat
class LameComponent extends React.Component {
render() {
return
{this.props.isGreat? 'Great': 'Lame'}

}
}
<LameComponent /> // this will render 
Great

I believe we need to go deeper right now, so buckle up. At this point, you still don’t know about RxDx you may check it from this link because I will explain how to connect RxDx to React.Component.

Stitching the RxDx with a React Component: A real-life example of HOC

Did you remember the selectors from Part 2 and store.select function from Part 1? This is the moment they will come in handy since we will use them as the cement between RxDx and React.Component. Store.select get a selector or a series of strings and return an observable to allow us to be notified of state updates. We can subscribe to all of these observables in componentDidMount and on each update we can re-render the component by using forceUpdate and to prevent memory leaks we have to unsubscribe from all subscriptions in componentWillUnmount:

class SomeUglyComponent extends Component {
componentDidMount() {
this.subscription = store
.select(someSelector)
.subscribe((update) => {
this.setState({data: update});
this.forceUpdate();
}
componentWillUnmount() {
this.subscription.unsubscribe();
}
render() {
return (
{ this.state.data }
);
}
}

Ok, I have to admit that this will work but SomeUglyComponent is not that ugly as we have only one of it. Let’s imagine we have to implement such components tens of, hundreds of times. Now it seems uglier, right? A generalized solution for this repeating task is required and the SomeUglyComponent should be as simple as possible so we can call it SimpleAndNiceComponent. The desired SimpleAndNiceComponent would be as follows:

const SimpleAndNiceComponent = connect({
data: store.select(someSlector)
})(({data}) =>
{data}
);
//or
@connect({
data: store.select(someSlector),
})
class SimpleAndNiceComponent extends Component {
render() {
const {data} = this.props;
return
{data}
;
}
}

So how do we achieve this simplicity and how we wire observables to props? The answer is hidden inside the HOCs. We need one step further than simple HOC, what we need is a HOC factory. I will implement a connect function which takes observables and returns a HOC which takes a React.Component and returns an enhanced/wrapped React.Component:

For the sake of clarity, the example above is simplified. For sure, if we need to use it for production, we have to think more about edge usage cases and debuggability and also error prevention and recovery strategies. Even though it’s a simplification this code piece will do the trick and will allow us to write simpler components with a generalized connect mechanism with async nature of observables and sync nature of React.Component.

Final, final, final words

Yes, finally we have all in one RxJS powered Redux equivalent library. All I can say that I learned a lot working on this experiment and I wanted to share it hoping that my journey will help others. Next steps will be using it, growing it and loving it!

If you managed to read up to this point and bared with me through this experiment, I will be extremely glad. A big thanks to you! Please don’t forget to clap or drop your comment below.

read original article here