What happens when you use RxJS in React?
Update (02.02.2019): more than two years ago, while experimenting with RxJS and React, I’ve created a library presented in this post. Please note that in the meantime, that library was deprecated.
Using observables seems like a good thing. So why don’t we use it in React apps more often?
With observables we can easily manage asynchronous data streams, but what is a stream in a React component?
Streams in React
To determine this, let’s start by analyzing a simple ClickCounter example:
This is a component describing asynchronous behavior. On every click
event on a button
tag, the state is changed. Or in other words, the state changes as a result of events happening over time.
A sequence of ongoing events ordered in time is a definition of a — stream.
So, instead of defining this.state
as an object which will later be overwritten, we can define it more declaratively:
Managing component streams
However, even when defined like this, how will our component know when to update? Somebody still has to invoke this.setState()
.
There are some existing solutions for achieving this, but it seemed a bit too complicated to me.
Other more popular options for using “Functional Reactive paradigm” requires you to use another framework or another programming language (like Cycle.js or elm).
But I didn’t like the idea of losing all good things React offers you.
So, I created a small library called Recycle, which is my attempt at solving this issue. It converts “functional/reactive object description” into a React component.
Here is how a ClickCounter looks like when defined using Recycle:
It works by “monkeypatching” React.createElement
. Before a component is rendered, if a select query is matched with node element, recycle sets inline event listener defined inupdate
function.
Each time event handler dispatches an event, it calls selectedNode.rxSubject.next(e)
In short, Recycle creates a classical React component out of this object by creating inline event handlers and handles component local state by using “Redux style” reducer operator.
Pros
- Greater separation of concerns between component presentation and component logic.
- You don’t need classes so each part of a component can be defined and tested separately.
- Component description is more consistent. There is no custom
handleClick
events orthis.setState
statements that you need to worry about. - State is calculated the same way as for redux store:
state = reducer(state, action)
. - Redux container looks like a normal component and it’s more clear what it does.
- Easy to use in an existing React application (choose components which you wish to convert).
Cons
- Observables. They come with trade-offs.
- You don’t like the idea of selecting nodes using class names, ids or tags
- Yo need to use advanced React API (like
forceUpdate
orshouldComponentUpdate
) - Yo need direct access to DOM elements (using
this.refs
) for external plugins or similar
Mailing list
If posts like this are interesting to you, consider subscribing to my mailing list. Don’t worry, I wont spam you — usually it takes me about two months for a single post :)