Home

Awesome

Quiescent

A lightweight ClojureScript abstraction over ReactJS, emphasizing its ability to (re)render immutable values efficiently.

An obligatory TodoMVC implementation is available.

See the documentation for instructions and examples of how to use Quiescent.

Rationale

ReactJS is an extremely interesting approach to UI rendering for HTML-based web applications. Its core value proposition is to make it possible to write one set of UI rendering code that works for both initial creation and any future updates. Updates are extremely efficient, because only the minimal set of necessary deltas are actually sent to the DOM.

In other words, React lets you write your UI code once, and still have a dynamic, data-driven application. Ideally, it eliminates any need to write explicit UI manipulation code. Instead, you are responsible only for supplying a specification of what the UI should look like, given certain data. The ReactJS implementation takes care of all the details of how to morph the existing DOM to correspond to changes in the input data.

Quiescent is intended to expose this feature and only this feature in a way that is convenient and idiomatic to ClojureScript, while remaining highly efficient.

It has the following design goals:

These goals differ slightly from other ClojureScript interfaces to React, as described below.

Comparison with Om

Om is another ClojureScript interface to ReactJS, highly capable and well-designed. It provides categorically more features than Quiescent, at the cost of taking more control and specifying more rigidly the way application state is modeled, updated and re-rendered.

The most important conceptual distinctions are:

Ultimately, though, Om is an excellent, well-thought-out library, and if your needs or design goals more closely align with its capabilities than with Quiescent, you should absolutely use it.

Comparison with Reagent

Reagent is another ClojureScript wrapper for ReactJS. It is, perhaps, easier than either Om or Quiescent and certainly the most readable of the three.

The key differences between Reagent and Quiescent (or Om, for that matter) are:

Although I do not have as much first-hand experience with Reagent, it seems to be a very convenient approach, and if it meets your needs you should definitely give it a try.

Implementation

This section presumes familiarity with how ReactJS works.

In short, basic Quiescent components implement only two of ReactJS's component lifecycle events:

  1. shouldComponentUpdate is always predicated exclusively on whether the immutable value passed to the component constructor function has changed. If so, the component re-renders. If not, it doesn't.

  2. The implementation of render is provided as a function supplied by the user. The output of this render function is presumed to be a single ReactJS component, as it is in vanilla ReactJS. The function, however, is passed the immutable value that was used to construct the function. It is also passed any additional arguments that were provided to the component constructor.

See Also

CHANGE LOG

0.2.0

Warning: This release contains breaking changes.

motivation for wrapper deprecation

As it turns out, there is no way in the current model that wrappers can provide the desired functionality in all cases.

A wrapper component can only modify its own lifecycle methods, not truly those of its child. But neither can it access the "shouldComponentUpdate" of the child - it must have a "shouldComponentUpdate" that constantly returns true. Therefore, an "onRender" wrapper would fire even if the wrapped component explicitly did not render due to an unchanged value (or otherwise overriding "shouldComponentUpdate").

0.1.2

License

Copyright © 2014-2015 Luke VanderHart

Distributed under the Eclipse Public License (see LICENSE file).