Building UIs with React
Filip Petkovski
In the 90s it was easy
- No RESTful APIs, no AJAX calls
- Refresh the page whenever the data changes
- JavaScript was simple
Fast forward to 2015
- Building [good] web apps requires teams
- Front end development is an engineering field
- JavaScript has become fast enough for many tasks
Web apps are still slow
- Native apps outperform web apps by a large margin
- Frameworks like AngularJS 1.x make things worse
- JavaScript execution is usually not the issue
- The DOM is used for the wrong purpose
What impedes DOM speed
- Frequent reflows and repaints
- A repaint has to verify the visibility of all other nodes
- A reflow affects the layout of the page
React overview
- React is only a view library
- Components and composition are central
- One way binding
- Virtual DOM
React component basics
- Components are state machines
- A component has internal state and external props
- Components can be nested and reused
- Written entirely in JavaScript or JSX
var Title = React.createClass({
render: function() {
return <h2>Form title</h2>
}
});
var TextInput = React.createClass({
render: function() {
return (
<div>
<input type="text" />
</div>
);
}
});
var Form = React.createClass({
render: function() {
return (
<div className="form">
<Title />
<TextInput />
</div>
);
}
});
var Title = React.createClass({
render: function() {
return <h2>{this.props.title}</h2>
}
});
var TextInput = React.createClass({
render: function() {
return (
<div>
<input type="text" />
</div>
);
}
});
var Form = React.createClass({
render: function() {
var title = 'Custom title';
return (
<div className="form">
<Title title={title} />
<TextInput />
</div>
);
}
});
var TextInput = React.createClass({
render: function() {
return (
<input type="text"
value={this.props.value}
onChange={this.props.changeHandler} />
);
}
});
var Form = React.createClass({
getInitialState: function() {
return { inputValue: 'Initial input value' };
},
changeInputValue: function(event) {
this.setState( { inputValue: event.target.value } );
},
render: function() {
var title = 'Custom title';
return (
<div className="form">
<Title title={title} />
<TextInput
value={this.state.inputValue}
changeHandler={this.changeInputValue} />
</div>
);
}
});
Why one-way binding?
- Achieving consistency is easy
- No unexpected performance drops
- Debugging is straightforward
What about performance?
var Form = React.createClass({
// ...
shouldComponentUpdate: function(nextProps, nextState) {
},
// ...
});
The case for immutability
- Immutable.js for immutable collections
- All modifications return a new collection
- Testing for equality between collections is trivial
Immutable.js in action
var Form = React.createClass({
// ...
shouldComponentUpdate: function(nextProps, nextState) {
return this.props.items !== nextProps.items;
},
// ...
});
- A light implementation of the in-browser DOM
Virtual DOM
First level properties of <div />
align, onwaiting, onvolumechange, ontimeupdate, onsuspend, onsubmit, onstalled, onshow, onselect, onseeking, onseeked, onscroll, onresize, onreset, onratechange, onprogress, onplaying, onplay, onpause, onmousewheel, onmouseup, onmouseover, onmouseout, onmousemove, onmouseleave, onmouseenter, onmousedown, onloadstart, onloadedmetadata, onloadeddata, onload, onkeyup, onkeypress, onkeydown, oninvalid, oninput, onfocus, onerror, onended, onemptied, ondurationchange, ondrop, ondragstart, ondragover, ondragleave, ondragenter, ondragend, ondrag, ondblclick, oncuechange, oncontextmenu, onclose, onclick, onchange, oncanplaythrough, oncanplay, oncancel, onblur, onabort, spellcheck, isContentEditable, contentEditable, outerText, innerText, accessKey, hidden, webkitdropzone, draggable, tabIndex, dir, translate, lang, title, childElementCount, lastElementChild, firstElementChild, children, nextElementSibling, previousElementSibling, onwheel, onwebkitfullscreenerror, onwebkitfullscreenchange, onselectstart, onsearch, onpaste, oncut, oncopy, onbeforepaste, onbeforecut, onbeforecopy, webkitShadowRoot, dataset, classList, className, outerHTML, innerHTML, scrollHeight, scrollWidth, scrollTop, scrollLeft, clientHeight, clientWidth, clientTop, clientLeft, offsetParent, offsetHeight, offsetWidth, offsetTop, offsetLeft, localName, prefix, namespaceURI, id, style, attributes, tagName, parentElement, textContent, baseURI, ownerDocument, nextSibling, previousSibling, lastChild, firstChild, childNodes, parentNode, nodeType, nodeValue, nodeName
Virtual DOM first level props
props, _owner, _lifeCycleState, _pendingProps, _pendingCallbacks, _pendingOwner
Virtual DOM
- Diffing algorithm.
- Batching DOM read/write operations.
- Efficient update of sub-trees.
Testing components
- Code is modularized and easy to test
- ReactTestUtils provide almost everything you need
- Shallow rendering for isolated structural testing
- JSDom for integration / behavioral tests
React Native
- Native development in JavaScript
- Native UI Views
- Layout offloaded to a separate thread
- Performance is top notch
Native Components
- <span> → <Text>
- <div> → <View>
- <img> → <Image>
React is:
- Simple
- Fast
- Testable
- Flexible
Thank you
Building UIs with React
By Filip Petkovski
Building UIs with React
- 1,244