Sunday, 30 November 2014

React.js Concepts

Overview

React.js is used to create components in your views, it specifically renders UI and responds to events.

Instagram and Facebook have come up with a FrontEnd client library that uses a virtual DOM diff implementation for ultra-high performance.  This works by comparing DOM changes in memory to calculate a patch required to update the DOM:

image

On every data change React re-renders the entire component in memory then uses a diff to apply a patch for what has changed in the DOM.  This means within React the virtual DOM UI is immutable, on each data change it’s completely replaced. 

Here is a stackoverflow comparing Angular’s dirty checking with Reacts virtual dom diffs, with the answer provided by the creator of React:

http://stackoverflow.com/questions/21109361/why-is-reacts-concept-of-virtual-dom-said-to-be-more-performant-than-dirty-mode

image

The syntax is a bit funky but quite simple once you get used to it.  It optionally uses a JSX transform library which is the preferred way of coding with React.  The following examples use JSX.

Concepts

React.createClass:  Creates a component by the developer providing a “render” function.

React.renderComponet:  Renders the component to a specified location

Props (or Properties):  Container object for immutable data, for example used with labels.  This example has two props: now and b.  Now is set to a javascript expression of todays date and b is set to a string literal.

image

Here is a more complex example showing default values, provided to React by using the getDefaultProps function, which are later overwritten by the component usage.

image

 

State:  Container object for mutable data for example used with input controls.  You can provide React the values for the initial state using the getInitialState function.  Here is an example of using state (note: state would usually be used with input controls rather than a label):

image

Controlled control:  Form component rendered with a value (or checked) property e.g.:

image

Mixins:  Common code that can be reused across components

ReactLink:  Used to streamline the updating of state so you don’t have to write your own onChange function to update state set.

image

Uncontrolled controls:  Form components rendered without a value (or checked) prop.  This enables React to ignore the component during the render process, allowing for better performance.  onChange event can still be used to detect changes outside of React.  You can also provide a defaultState value.  Beware, as React will not be tracking this component this will cause divergence from Reacts virtual DOM.

image

Ref:  Similar to the “ID” attribute in HTML, this attribute allows fast access to an item within your component instance:

image

getDOMNode(): Gets the underlying DOM node from an item within a React component instance.

PropType validation: By providing a propTypes property object you can validate your properties.  This example states the now property must be a string and the b property must be great than 5.

image

Flux:  Facebook have a separate optional complimentary library called Flux for single (or uni) directional data flow.  They have done this by introducing a dispatcher and (data) store.

image

The Dispatcher acts as a “traffic controller” for all the actions.

The (data) Store is the data layer that updates whenever it receives a new action from the dispatcher.

Thursday, 27 November 2014

Resolve promises in router, defer controllers

Taken from this style guide:  http://toddmotto.com/opinionated-angular-js-styleguide-for-teams/

After creating services, we will likely inject them into a controller, call them and bind any new data that comes in. This becomes problematic of keeping controllers tidy and resolving the right data.

Thankfully, using angular-route.js (or a third party such as ui-router.js) we can use a resolve property to resolve the next view's promises before the page is served to us. This means our controllers are instantiated when all data is available, which means zero function calls.

Bad:
function MainCtrl (SomeService) {

var self = this;

// unresolved
self.something;

// resolved asynchronously
SomeService.doSomething().then(function (response) {
self.something = response;
});

}
angular
.module('app')
.controller('MainCtrl', MainCtrl);

Good:
function config ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
resolve: {
doSomething: function (SomeService) {
return SomeService.doSomething();
}
}
});
}
angular
.module('app')
.config(config);

At this point, our service will internally bind the response of the promise to another Object which we can reference in our "deferred-instantiated" controller:

Good:
function MainCtrl (SomeService) {
// resolved!
this.something = SomeService.something;
}
angular
.module('app')
.controller('MainCtrl', MainCtrl);

We can go one better, however and create a resolve property on our own Controllers to couple the resolves with the Controllers and avoid logic in the router.

Best:
// config with resolve pointing to relevant controller
function config ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
controllerAs: 'main',
resolve: MainCtrl.resolve
});
}
// controller as usual
function MainCtrl (SomeService) {
// resolved!
this.something = SomeService.something;
}
// create the resolved property
MainCtrl.resolve = {
doSomething: function (SomeService) {
return SomeService.doSomething();
}
};

angular
.module('app')
.controller('MainCtrl', MainCtrl)
.config(config);

Route changes and ajax spinners

While the routes are being resolved we want to show the user something to indicate progress. Angular will fire the $routeChangeStart event as we navigate away from the page, which we can show some form of loading and ajax spinner, which can then be removed on the $routeChangeSuccess event (see docs).