The claim that React is fast because of the virtual DOM has the causation backwards. Rendering a component tree into a JavaScript object graph and diffing it against the previous one is strictly more work than setting textContent on the one node that changed. What it buys is that you no longer have to know which node that was.
// the hand-written update: correct only while every path is covered
function update(order) {
document.getElementById('total').textContent = order.total;
document.getElementById('status').className = 'badge ' + order.status;
// and the six other branches somebody will forget
}
// the React version: describe the whole thing, every time
var Order = React.createClass({
render: function () {
return React.DOM.div({className: 'order'},
React.DOM.span({className: 'total'}, this.props.order.total),
React.DOM.span({className: 'badge ' + this.props.order.status})
);
}
});
React.renderComponent(Order({order: order}), document.getElementById('app'));
The diff exists to make the naive thing — throw the description away and build a new one on every change — cheap enough to be acceptable. It is not free, and it is not faster than a targeted update; it is faster than the targeted update you were going to get wrong on the ninth branch. Two consequences follow. The reconciler needs stable key props on lists or it recreates nodes it could have moved, which is where most “React is slow” reports come from. And it only ever compares against its own previous output, so anything else mutating the same DOM — a jQuery plugin, a third-party widget — is invisible to it and gets destroyed on the next render. Worth a look this year; I would not put it inside an existing jQuery page yet.