React Hooks + RxJS or How React Is Meant to Be

Never miss a story from Soshace
Looks good!
Please enter correct name
Please enter correct email
Looks good!
Please confirm to subscribe!
artwork depicting React and RxJS logo with a hook

We’re hooked!

I remember when I first got introduced to React. I was stunned by how great the idea of handling all of the presentation logic with just javascript and JSX was, and even more so: how effortless it seemed at first–you pass in props, update states. How easy!

Going through the first Tic-Tac-Toe tutorial on the React homepage felt so great, I was confident that humanity has finally found the magic bullet, at least for the front-end.

But… there was a caveat. What if we lifted the state five floors up, but some of that state and state update logic was still needed on the first floor?

How about we pass some state one level down, then some of that state one level further and so on till it reaches the component? That’s a bit laborious but ok.

Oh, I forget, I need to change the shape of the state on the fifth floor… and props on the fourth… and props on the third… second… first…

Ouch! Is it by mistake or design? Turns out this state-to-props issue is by design, and this is where Redux steals the show. However, five minutes into the Redux tutorial you begin to realize that your excitement about React was an overreaction… or was it?

There were many attempts I know of to steal the show back for React, to name a few: React Context API as well as various state managers; but for me, none of them got the excitement I initially had for React back… except when I learned about RxJS.

Analysis

This article’s main goal is to justify that the RxJS and React combo allows for better readability, less boilerplate and being closer to React while allowing the same functionality as the popular state management frameworks and not being a framework itself. Let’s look at this approach more closely.

Better readability & less boilerplate

Artwork depicting code mockup that the developer who wrote it doesn't recognize

We’ve all had these moments

Readability is one of the first things I pay attention to as I choose a tool I am going to be working with. For me, the main criterion upon which I evaluate the quality of my own code is how well am I able to understand it a week after and a month after it was written.

Of course, the tool you are using isn’t always as impacting on your code readability and self-documentability as much as your own set of habits and choices, but it still may be a contributing factor nonetheless. In my experience, the more verbosity and indirection is associated with creating a specific functionality, the less you will be able to understand it later on.

And this is true of Redux. Before even getting to the core of what it is you are doing, you have to write your actions (some people write action creators on top of that), create reducers, compose them, connect dispatch and state to props, and only then introduce the logic, and don’t forget you have to write sagas or thunks for side effects.

When you are trying to understand the structure of a Redux application, you are facing similar challenges, you have to understand what actions trigger what side effects, what happens in reducers and how it all fits together. I’ve always considered it being a nightmare, and, despite my many attempts, never really understood my colleagues who were very passionate about Redux. I would say Redux and readability are essentially the opposites. Feel free to disagree, but please make an educated argument in the comments for me and other people to be able to learn.

MobX significantly improves the readability aspect by not having the verbosity and indirection of Redux. Yet it can be confusing to mentally derive the structure of the state that consists of composed stores, as they can become a mess of properties and update logic. So how does it compare to the RxJS Hook?

Since you’re essentially using RxJS Hook as the familiar useState hook, it should be very easy to read and understand. Your state lives inside of a Subject that you can always retrieve later and analyze as you are trying to understand what the application is doing.

Close to React

artwork depicting various parts of the React ecosystem

It’s quite an atomic family

React is elegant. The state managers are not. Period. If there is an opportunity to stay with React before introducing other frameworks, I will use that opportunity. I am convinced that you should be able to compose complex and elegant application code with essentially React and Services logic while not sacrificing readability, maintainability, and scalability.

RxJS and React Hooks are actually the combination I find extremely helpful in this regard. Having actually written production code with this, I can tell you from my experience that it was and still is a great ride.

State Management Functionality

artwork depicting various stages of an atom

Creation of the modern front-end universe

I never really understood the popularity of Redux. Don’t get me wrong, I always thought it was pretty interesting, but I never liked writing my code using it. I wonder if its popularity really comes from the fact that people like Dan Abramov, who is a great guy and a great engineer, but it doesn’t make sense why it would still worth biting the bullet.

The main merit of Redux for me is in its three principles of course, which are:

  • Single source of truth
  • State is read-only
  • Changes are made by pure functions

So none of these principles actually work for MobX! With MobX you don’t have a centralized state object. You have a centralized store object. Know the difference. 😉
And since you don’t have a centralized state object, you can’t use it to easily reason about your application as your stores and your state are interleaved and can be pretty hard to unravel.

With RxJS Subjects and React Hooks we get the one principle out of the box – the pure-functions, as observable streams are themselves pure-functions. Unfortunately, the state of a BehaviorSubject is not read-only, and you can manually change it after you get it with getValue(). I will try to ask the community if it is possible to make it read-only out of the box so that you can’t shoot yourself in the foot with this, as I am pretty sure it could just be something the contributors have overlooked. But as to the single source of truth, it is actually not that difficult to introduce by composing all the subjects into one observable, similar to how you compose reducers together.

Single Source of Truth

In general, the RxJS Hook approach is not that different from Flux. You have:

  • Dispatcher/action – subject.next() / setSharedState()
  • Store – globalObservable
  • View – well, your view

TL;DR

So here is your shared state!

Nothing unusual: we are getting a tuple of value and setState function.

Do you want to use it like useState?

Easy!

subject.next is another way to update the logic, but I think setState from the tuple makes it more readable and easy to understand.

Do you want it to be shared between components at the top of the tree as well as the bottom?

Easy!

Notice that we can use the same state easily, where in the past you would have to pass everything through props.

Do you want to use both local and shared states?

Easy!

Another great thing is that you actually can have multiple little states as part of your component state.

Oh, but what if I want to update this state outside the component…

Easy!

artwork depicting Neo from the Matrix movie

Or so the course certificate says

You can update state from anywhere in the application, by just using subject.next. It is extremely useful! MobX and Redux could never give you this much freedom.

Still not convinced?

I rewrote the Redux tutorial using the RxJS Hooks approach. Feel free to compare two codebases that do the same thing. Here‘s the original Redux Reddit Tutorial and here‘s the React + RxJS Reddit Tutorial.

Side Notes

I think somebody brought to my attention that using components with subjects makes them tightly coupled. It is true in a sense where, for example, you are importing something from an external library which makes a hard dependency. But having hard dependencies doesn’t mean you can’t make whatever it is you are building highly reusable. A styled component inside of my custom component is a hard dependency, but it is abstracted out when I import my custom component. The same goes for this approach.

Conclusion

Behind the custom hook is a little pretty eight-liner:

artwork depicting Neo from the Matrix movie

Just an ordinary day of a React developer

Is this really new?

Not really, there are many blog posts about similar concepts, but in my opinion, people always slide into the complexity trap and start to introduce new frameworks.

This article is almost a mirror of this one. I didn’t know there was an article about essentially the same thing. I assure you I came up with this independently. But this doesn’t really matter. What matters is to be faithful to React’s promise: React makes it painless to create interactive UIs. and try to avoid the unnecessary complexity of introducing a new state manager or a framework, this is so besides the point! (Sorry Akita, but you fell into that trap)

Never miss a story from Soshace
Looks good!
Please enter correct name
Please enter correct email
Looks good!
Please confirm to subscribe!

Related articles

18 Best Web Development Blogs on Medium

In this article, we cover the best Medium blogs on web development and>>>

Blogs
5.08.2019

Introduction to WebAssembly: The Magic of Native Code in Web Apps

WebAssembly might have the potential to reshape the entire web development landscape — just like JavaScript when it was introduced back in 1995. In>>>

JavaScript

Monthly Digest of the Most Popular JS Github Repositories

In the following blog post, we’ll cover the most popular GitHub JavaScript repositories as of July 2019.>>>

JavaScript