ReduRx: More App, Less Code

As of this writing ReduRx, my take on the Redux pattern implemented with observables, is at version 0.3.3; so I thought I’d do a simple write-up with some examples to give a general idea of what ReduRx is and why you might use it. In writing example applications for the library; I’ve found that it does more than I expected, and that you can do a whole lot without a lot of code. So here’s the rationale behind the library, along with some examples of the unique features exposed via ReduRx. If this is tl;dr checkout the TodoMVC and ReTweet examples in the ReduRx repository, otherwise read on.
First, why build it at all. I’ve spent a lot of time writing Redux apps; so I’ve spent a lot of time writing action types, and action creators, and reducers with switch statements, using middleware; all that jazz. When I heard about RxJS, which implements the observable pattern in JavaScript, I wondered if there was a way to get the same pattern of Redux using observables. So to test out that theory I built ReduRx. It started out as an experiment, and ended up being a pretty powerful tool. ReduRx is like Redux, in that you get the same pattern, but minus the boilerplate and plus observables. So let’s start with the base of any application, state, and see how that’s possible
State…the data frontier
All applications have state. In fact all things in the world could be said to have state. If you woke up in the morning and I asked you “What’s your physical and emotional state”; you might say “I’m rested, hungry, and ready for the day!” Maybe without the enthusiasm… As the day goes on and events occur, like dinner, that state changes. If I asked you the same question in the evening, you might say “I’m tired, full, and ready for bed.”
Your application is the same way. The state of your application is the collection of values that the logic of your app acts upon, so you need some way to store state. State changes as events occur in your application, and so you need some way to change state. You also want to know when this state changes, so you’ll want some way to subscribe to state. ReduRx implements all these features using a compact syntax. First, let’s look at a simple and complete example; a counter application:
So here we have state, a counter, and we put that state in a container using the createState function. In doing so we convert the object into a tree of observables, where we can reduce and observe any value at any level. Each node in the tree is an accessor function, so from the root node we access the node for the counter. Then we subscribe to that node’s observable, and console log its value whenever it changes. Once we call state.connect; that subscription activates and we see the initial value for the counter logged to the console. Now that we have state we can subscribe to, we need some way to change that state in response to events. Enter ReduRx actions:
Here we define two basic actions; increment and decrement. The nodes in the tree also implement a reduce function, which takes one or more observables, actions, or state nodes; and reduces state in response to those observables emitting values. In this case we take the previous state and increment or decrement the counter. When we call these action functions, we see the new state logged to the console.
Real world features
Instead of breaking down an entire application, for the sake of brevity I’ll highlight a few useful scenarios and how to approach them using ReduRx. For complete examples check out the examples directory in the ReduRx repository. First situation…ajax and promises. Because ReduRx has observables built in, you can handle async and promises easily, no middleware required:
The additional concept introduced here is the callback passed to createAction. This callback takes the base observable for the action as an argument, and returns a transformed observable to be used by the action. In this case, every time the retrieveMessages action is called, we make a request to our API for some data. When the promise resolves, the action observable will emit the resolved value, which will invoke the reducer passing that value.
Second situation, computing state from state. In the good ole’ TodoMVC application, we have a base list of todos, and a filtered list of todos we’d like to display. If you look at the current Redux TodoMVC example, this filtered list is calculated within a component and stored there as state. If you can observe state directly, and transform state with a simple focused reducer, why not just do it at the state level instead?
Because we can reduce state using any observable (or any object with an asObservable method like the state nodes in this case), we’re not limited to using only actions, we can use state to compute state. Inception…
The final scenario I’ll share makes use of some RxJS observable features to simplify application logic. This example hits the GitHub Gist API (in reality you need an OAuth token, but I’ve left that out), and requests all new Gists that have been updated since the last refresh. If the action is triggered, it starts an interval of sixty seconds and requests on that interval. If the action is triggered in the meantime (by an impatient user) it will make a request and restart the interval over again. To protect our API Rate Limit from a really impatient user, we want to debounce the refresh action by half a second:
Making use of interval observables, and the debounce, flatMapLatest, timeInterval observable methods, this logic is pretty straightforward to implement without reinventing the wheel.
So in conclusion, ReduRx gives you the essential pattern of Redux with the power of observables. This let’s you write more logic with less boilerplate, and gives you a rich pipeline to transform events into state. It’s still in an early stage, but I think it’s definitely worth taking for a spin. For more info and examples check out the repository, and if you like it give it a try, and if you really like it think about contributing. Thanks, and happy coding!