Reactive.js is a pure Javascript library inspired by Functional Reactive Programming. If you’ve ever used Excel or another spreadsheet program, you’ve already done something like FRP.
Reactive.js aims to bring FRP to Javascript by augmenting Javascript functions, allowing you to declare data flows in your code by representing your values as reactive functions that depend on one and other. Complicated UIs, data visualizations, and systems of calculations are examples of just a few problems that can be simplified by using reactive programming.
Reactive.js is already being used in production on Wealthfront.com, where it’s helping us gracefully manage the interconnection of portfolio model calculations, visualizations and UI elements. Check out a sample plan to see what I mean (it’s pretty neat).
If you’ve never heard of FRP before I’ll step you through some basics and show you how Javascript (and Reactive.js) enter the picture. You can also grab Reactive.js on github right now, the README provides a walkthrough and introduces the API if you’d prefer to jump right in.
Reactive Programming in 60 seconds
In Reactive programming it’s easier to think of our variables as expressions, not as assignments. In order to understand the difference, consider the statement “a = b + c
“.
There are two ways to look at this. One is the way we are used to, “a
is assigned to the sum of b
and c
, at the instant this is interpreted”, which is what we’d expect in Javascript or any other imperative language.
But we could also read it as “a
represents the sum of b
and c
, at any point in time.” This interpretation is not really so strange, that’s exactly how we would expect things to work in a spreadsheet. If we had a spreadsheet cell containing the expression “=B+C
“, the value in that cell would change as the cells B and C change, wouldn’t it?
Reactive programming means we describe our program using the second interpretation. We don’t assign variables, we express them, and they don’t represent discrete values, they represent a value that changes over time.
Reactive Programming in Javascript
Obviously Javascript is not a reactive language, but there are advantages to being able to express ourselves reactively. Reactive programming can be immensely useful in describing systems of equations, complicated UIs, and data visualizations to name a few.
So let’s reexamine our earlier statement about reactive programming, then we’ll see how Javascript fits into the picture (and how Reactive.js fits into Javascript).
“We don’t assign variables, we express them…”
In Javascript, a = b + c
assigns a value. For us to accomplish our goal, however, we need to describe what a
represents using an expression (like =B+C
in a spreadsheet). Javascript does have expressions, they’re called functions! So in reactive programming a given value, like a
in a = b + c
is expressed as a function:
var a = function (b,c) { return b + c } // a = b + c
This brings us to our first conclusion.
Conclusion 1: Our variables are expressions, so our variables are functions.
Now lets consider the rest of the sentence:
“…and they don’t represent discrete values, they represent a value that changes over time“
When you write =B+C
in a spreadsheet, your spreadsheet program notes that your cell is relying on the values of B and C. It starts to assemble a dependency graph internally that it can use to keep track of changes. It traverses that graph when B or C change, updating A in the process. Most importantly, we don’t have to write a “calculate all” function because the spreadsheet program handles that for us.
Unfortunately Javascript won’t magically track dependencies, so it’s not enough to describe our variables as expressions, we also need to tell our expressions what they depend on. Only then can they be smart enough to update each other automatically.
Conclusion 2: We have to tell our expressions what they depend on.
When we combine our two conclusions, we arrive at the following:
Our variables are expressions, so our variables are functions. And we have to tell our expressions what they depend on, so that means we have to tell our functions what they depend on.
Fortunately for you, Reactive.js does just that.
Using Reactive.js
At its core, Reactive.js is just a single method, $R()
. $R()
accepts a function and returns you an augmented version of that function that is meant to represent a value in your program. How is it augmented exactly? “Reactive functions” gain a new method called .bindTo()
. bindTo()
accepts one or more reactive functions, and binds them to your function’s arguments via partial application.
Don’t worry about $R.state yet, it just returns a reactive function that gets and sets internal state (handy for literal values) — the docs explain it in more detail.
//A = B + C
var reactiveA = $R(function (b, c) { return b + c });
var reactiveB = $R.state(2);
var reactiveC = $R.state(1);
reactiveA.bindTo(reactiveB, reactiveC);
reactiveA(); //-> 3
reactiveB(5); //Set reactiveB to 5
reactiveC(10); //Set reactiveC to 10
reactiveA(); //-> 15
That’s it. As you can see, Reactive.js asks you to express values as functions and gives you the tools you need to tell those functions how they depend on each other. In the example above, any time reactiveA
or reactiveB
change, reactiveC
will change too. reactiveC
isn’t assigned a+b
, it represents a+b
at any moment in time.
An example with time
Since we talk about variables representing a value that changes over time, let’s actually create variables that depend on, well, a value that changes over time.
Reactive.js is minimal
Reactive.js seeks to be as minimal and unobtrusive as possible. Because it operates on, and returns, normal Javascript functions, it’s very easy to integrate into existing code. If you start writing “reactive” code, any existing function can be integrated as a dependency by creating a reactive version of it with $R()
.