reactive.coffee

FAQ

Why yet another client-side framework?

See Motivation and Design Rationale.

How does Reactive stack up against the many other client-side frameworks?

See Related Work.

Isn't this approach just reverting back to the PHP days of mixing markup and logic?

Reactive is designed for rich application development. Rather than focusing on the division between markup and logic, Reactive focuses on separating models from views and on the component abstraction. Components must encapsulate not just markup, but also behavior. The two should be coupled, not separated.

This library also takes the stance that logic-less is generally a counter-productive endeavor---the logic-less-ness and associated gains are primarily superficial, readability can be adversely affected, and it does not separate concerns. Others have written more on this.

Why jQuery / what is the relationship between Reactive Coffee and jQuery?

The library just uses jQuery as a cross-browser interface to the DOM for its own operations. All tags are wrapped in jQuery objects. You don't need to use jQuery, but jQuery excels as a cross-platform API and is probably the most popular of managing low-level DOM operations. Although jQuery is known to not scale very well, higher-level application structure is where Reactive Coffee steps in.

Why the syntax noise in the template language?

This is actually not set in stone. The framework could handle a more concise template syntax. For instance, it's certainly feasible to support a language in which one of the above examples could be rewritten as:

div '.sidebar', [
  h2 'Send a message'
  form {action: '/msg', method: 'POST'}, [
    input {type: 'text', name: 'comment', placeholder: 'Your message'}
    select {name: 'recipient'}, [
      option {value: '0'}, 'John'
      option {value: '1'}, 'Jane'
    ]
  ]
]

This would be closer to the concision of languages like Slim and Jade:

.sidebar
  h2 Send a message
  form(action='/msg' method='POST')
    input(type='text' name='comment' placeholder='Your message')
    select(name='recipient')
      option(value='0') John
      option(value='0') Jane

However, the project currently errs on the side of more conservatively adding syntax to the DSL, and defaulting to strictness.

Why not use Knockout observables?

Reactive originally tried simply reusing KO, but ultimately divorced itself since there are both desired features that are missing (differences in array event propagation, topologically ordered batch propagations, etc.) and features that are unwanted (mis-matched programming model, larger API surface area, etc.).

Why did you choose to use rx as the namespace? You know about Reactive Extensions, right?

Yes, it's cited in the list of Related Work. We chose rx because short namespaces are convenient and it's unlikely you're using RxJS if you're using reactive.coffee, but please correct us if we're wrong.

Do I need to sprinkle rx.cell() everywhere in my model?

You actually don't. At one extreme, you can always fall back to just wrapping your entire model in a single cell, and re-render everything on changes, which is sufficient for small/simple applications.

However, there are other benefits to systematically using rx.cell() besides its performance scalability, including debugging and introspection of what the DAG of dependencies looks like in a running application (on a finer granularity than "views depend on model"). Additionally, applications may want to manually create subscriptions to events only on parts or certain cells of the model, in which case referencing cells is the clearest and most direct way to do so, rather than needing to compute diffs on your full model.

An in-between optimization would be to have a system that figures out the diffs for you (variants of which are found in other frameworks including Angular and React), such that at least DOM changes are localized. For more complex applications, though, where you may have multiple "layers" of models and view-models, cells scale. Also, in the future, we may get the best of both worlds—take a look at Object.observe. For more on these directions, see Ideas.

Can I use this from JavaScript?

Yes, you can. The main benefit of using CoffeeScript here is that it has a very DSL-friendly syntax for Reactive's declarative UIs, and particularly for the terse anonymous function syntax to represent the incrementally recomputable bindings. Otherwise, it's pretty similar.

It's worth showing a quick example of what that would look like:

var $sidebar = rx.bind(function() { return
  div({class: 'sidebar'}, [
    h2({}, 'Send a message'),
    form({action: '/msg', method: 'POST'}, [
      input({type: 'text', name: 'comment', placeholder: 'Your message'}),
      select({name: 'recipient'}, users.map(function (user) { return
        option({value: ""+user.id}, [user.name]);
      }))
    ])
  ])
});