Facebook is changing 'app' development and they are pioneering (for the web) a new category of application some call 'unidirectional'. Two key behaviours are described here:
Other frameworks and tools are beginning to adopt these techniques. Ember.js, mercury and Angular 2. Support for Facebook's immutable-js will be added to Angular 2. Facebook is credited with pioneering these concepts.
A React app fully re-renders itself on each UI event and is always composed of static data and relationships. This differs from typical web apps that modify themselves through event-driven changes accumulating over time. The idea is that managing static data is easier than managing data that changes over time.
dynamic mutable | static immutable |
---|---|
A typical application is composed of local object-states 'observing' one another. Objects send and receive 'events' from one-another, updating the document as they go. Events are handled at different locations throughout the document. Relationships are managed over time as objects are added, removed and replaced during the life of the document. Small, islands of state with evolving relationships.
A unidirectional application is composed of an intermediate tree state called a vtree. Events affecting state produce new vtrees that are published to the document. All Events go to a single input at the top of the tree/document. There are no two-way data-bindings and no mutable references. No 'event-observer' category of problems. amazing
Representing the document with a clearly defined tree is a good idea.
Click 'delete' on an item in your shopping cart and a new page is requested. The server deletes a row from cart and renders a response with rows remaining. This is how web pages were done before single-page-apps appeared and conceptually this is how React does them.
This also parallels the way video game-engines work.
Benchmarks show Om (React) is comparably faster at than a Backbone MVC when rendering todo list updates.
Components are declarative. They do not observe or keep state. A node in the vtree represents the state of each component. For example, a text-input
component returns text-input
HTML, by reading a text-input
-type node. It only reads node properties and returns a predictable result.
All related nodes are used with the same component and there's no need to make special component instances for each node.
For example, render methods found in React and Mercury. These return rendered results from a node:
TodoApp.react.js (React)
render: function() {
return (
<div>
<Header />
<MainSection
allTodos={this.state.allTodos}
areAllComplete={this.state.areAllComplete}
/>
<Footer allTodos={this.state.allTodos} />
</div>
);
},
login-component-render.js (Mercury)
function render(state) {
return state.registerMode ?
renderRegister(state) :
renderLogin(state);
}
Statically composed applications are easier to debug and test. To test a component method, call the method with a node and assert the correct result was returned.
Because vtrees have no circular or upward references they are readily converted to and from JSON strings that can be conveniently stored and shared.
Examples:
The virtual DOM (vdom) is an abstraction through which a vtree is published to the document. nodes at the new vtree are 'reconciled' against those in the previous vtree to discover changed nodes (tree-diffing). The minimum document mutations are identified, queued and finally batch executed to the document.
A side note is that the Tree-diffing problem is complex. Tree-diffing is an O(n3) problem. Optimal (worst-case) solutions will make ~1 billion comparisons for 1,000 nodes. Clever constraints give React a complexity of O(n). A React-tree-diffing walk through is found here (Christopher Chedeau) warning: interesting.
Complimenting the Virtual DOM are synthetic events. A browser event like 'onclick' is used to create a normalised onclick event that is bubbled up the vtree. The Virtual DOM and synthetic events are form what is called an 'intermediate' layer.
The intermediate layer makes it possible to programmatically send events to the application and observe a result without a browser environment.
The intermediate layer may also be used as an interface for updating information in alternative contexts. A vtree and event pair may be used to publish information to a browser canvas element or a native iOS application.
Other concepts around React worth linking to (I'll comment on these):
dynamic mutable | static immutable |
---|---|
circular and upward data flows | one-directional data flows |
mutable changeable structures | immutable persistent structures |
multiple inputs for events | one input for all events |
difficult undo | easy undo, timetravel, sharing |
fragmented local state centers | monolithic aggregate state centers |
increased DOM reliance | decreased or no DOM reliance |
many state changes, each ui event | one new state, each ui event |
Browser and DOM-centric | multi-platform |
two-way data binding | one-way data binding |
indeterminate tree structure | clearly identified tree structure |