React & Virtual DOM

Swarup Karavadi

@swazza85

diff-patch-apply

What is Virtual DOM

  • A tree data structure that represents a View at any given point in time.
  • Introduced by ReactJS.

ReactJS

  • Framework created by Facebook.
  • Facebook wanted to build a UI framework that would
    • Allow for greater "composability".
    • Minimize side effects of mutations.

Mutations

  • Mutation === change
  • Mutations are directional
  • Can be data => view (ex - receive ajax response and update view)
  • Can be view => data (ex - user interactions resulting in model updates)
  • Mutations have side effects
  • Bi-directional mutation === two way data binding
  • Side effects of bi-directional mutations are not trivial to reason about

Mutation Side Effects

{0} $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: {1}
  • How often have you come across code like this?
  • How much time have you spent debugging trying to find what caused the digest cycles to go into an infinite loop?
  • What if you could make your code easier to reason about?
  • Enter Uni-directional data-flows

ReactJS and Uni-directional dataflow

  • Mutations flow from data to the view
  • Any user interactions do not directly alter model data 
  • User interactions are communicated to interested parties via custom events
  • How would you implement this - 

Angular Example

  • The 'span' element has no control over when it's value changes.
  • The 'span' element's state change is driven from external factors.

The React Way

  • The 'span' component has complete control over its state.
  • It has explicit control on when it would like to update its state by subscribing to interesting events.
  • Self contained component
    • Easier to reason about
  • Basis of Flux architecture

Time for some Code

var ee = new EventEmitter()
      
var reactInput = React.createClass({
    getInitialState: function () {
      return { value: "" };
    },
    onInputChange: function(e) {
      var newValue = e.target.value;
      el.setState({value: newValue});
      ee.emitEvent('valueChanged', [newValue]);
    },
    render: function() {
      return React.createElement("input", { type: "text", onChange: this.onInputChange, value: this.state.value })
    }
});

var reactSpan = React.createClass({
    getInitialState: function () {
      return { value: "" }
    },
    componentWillMount: function () {
      ee.addListener('valueChanged', function(newValue) {
        el2.setState({ value: newValue });
      });
    },
    render: function () {
      return React.createElement("span", null, this.state.value)
    }
});

var el = React.render(React.createElement(reactInput), document.getElementById("mountNode"))
var el2 = React.render(React.createElement(reactSpan), document.getElementById("mountNode1"))

Enter the V-DOM

Essence of V-DOM

// Time T0
var tree = render(getData());           
var rootNode = createElement(tree);     
var vdom = document.getElementById("vdomRoot");
vdom.appendChild(rootNode);
// Time T1
var newTree = render(getData());               
var patches = diff(tree, newTree);				
rootNode = patch(rootNode, patches);				
tree = newTree; 
// Time TN
var newTree = render(getData());               
var patches = diff(tree, newTree);				
rootNode = patch(rootNode, patches);				
tree = newTree; 

What Next

  • https://github.com/Matt-Esch/virtual-dom
  • Whole bunch of libraries inspired by V-DOM. Check em out at http://vdom-benchmark.github.io/vdom-benchmark/
  • React Native
  • Flux Architecture

On a parting note - Angular vs React: Percieved Performance

  • Stress test
  • Bind data to a 500 row table with 4 columns - 2000 data bindings
  • Do this in a setInterval of 0.

Angular

React

The Virtual DOM

By Swarup Karavadi

The Virtual DOM

  • 1,292