Angular

+

React.js

or rather....

Choosing Wisely

and the role of abstraction

Careful Consideration

  • Avoid False Dichotomies
  • Learn From the Past
  • Optimize Selection for YOUR Usecase
  • Understand The "Worldview" of a Tool
  • Consider the level of Abstraction

False Dichotomies

We are embarassingly bad at this in the tech industry.

Two options are presented, and third options are available, sometimes numerous options.

Two options are so similar, and cover such similar concerns, they are equally effective.

The two options don't even cover the same concerns, and therefore shouldn't really be compared.

Knockout

Backbone

Bootstrap

jQuery UI

Angular

Ember

Angular

React

Gulp

Grunt

Less

Sass

Bower

Browserify

"With angular, you are basically passing your data through these things called scopes. That's a very leaky abstraction. It forces you to compose an app, not in terms of functions and objects, but in terms of directives and their "flavor" of Model View Controller.

As you scale up, you start to miss the last 40 or 50 years of research of how to abstract a program"

- Pete Hunt

When selecting anything, 

Ask yourself.

What does the tool abstract?

Angular

  • Fullstack Concern
  • Includes templating
  • Application build using Directives
  • 2 Way Data Binding
  • Dependency Injection
  • Composed of modules
  • Providers:
    • Services
    • Factories
    • Values/Constants
  • UI-Router for routing.
  • Highly Declarative

Directives

Directives are the lord of the dance. They are essentially a configuration object that takes all the other elements, and via magic and lazers turns them into declarative html.

angular
    .module('angledditApp')
    .directive('subredditMenuItem', function () {
        return {
            templateUrl: './partials/subreddit-menu-item.html',
            restrict: 'E',
            scope: {
                subreddit: '@',
                pages: '@',
                renderer: '@'
            },
            link: function link($scope, $el, $attrs){
                //dom manipulation would be here.
            },
            controller: function ($scope, $state, $stateParams) {
                function navigate(subreddit, pages, renderer) {
                    $stateParams.pages = parseInt(pages);
                    $stateParams.subreddit = subreddit;
                    $state.go('angleddit.' + renderer, $stateParams);
                }

                $scope.navigate = navigate;
            }
        };
    });
angular
    .module('angledditApp')
    .directive('subredditMenuItem', function () {
        return {
            templateUrl: './partials/subreddit-menu-item.html',
            restrict: 'E',
            scope: {
                subreddit: '@',
                pages: '@',
                renderer: '@'
            },
            link: function link($scope, $el, $attrs){
                //dom manipulation would be here.
            },
            controller: function ($scope, $state, $stateParams) {
                function navigate(subreddit, pages, renderer) {
                    $stateParams.pages = parseInt(pages);
                    $stateParams.subreddit = subreddit;
                    $state.go('angleddit.' + renderer, $stateParams);
                }
                $scope.navigate = navigate;
            }
        };
    });
 <div ng-repeat="subreddit in subreddits" class=" btn btn-default">
      <subreddit-Menu-Item 
                           subreddit="{{subreddit.display_name}}" 
                           pages="{{pages}}"
                           renderer = "{{renderer}}"
                           ></subreddit-Menu-Item>
</div>
            controller: function ($scope, $state, $stateParams) {
                function navigate(subreddit, pages, renderer) {
                    $stateParams.pages = parseInt(pages);
                    $stateParams.subreddit = subreddit;
                    $state.go('angleddit.' + renderer, $stateParams);
                }
                $scope.navigate = navigate;
            }

$scope

 and

2 providers; 

$state

and $stateParams are being injected into the controller

Providers + DI

scope: {
      subreddit: '@',
      pages: '@',
      renderer: '@'
}
<subreddit-Menu-Item 
                     subreddit="{{subreddit.display_name}}" 
                     pages="{{pages}}"
                     renderer = "{{renderer}}"
                     ></subreddit-Menu-Item>
controller: function ($scope, $state, $stateParams) {
    function navigate(subreddit, pages, renderer) {
        $stateParams.pages = parseInt(pages);
        $stateParams.subreddit = subreddit;
        $state.go('angleddit.' + renderer, $stateParams);
    }
    $scope.navigate = navigate;
}

$scope

Scope, is essentailly like the public members of a revealing module. Public to the template itself, and modifiable via controller and link

 DOM attr

2-way scope

expression

The Dream

Create compositable, declarative components you just drop into a page and they work

<my-totallysick-dashboard data="data" />

Many Have Shared this Dream

  • Web Components
  • Web Forms/ Templated controls
  • Html itself

Real Talk

  • Many things are VERY good candidates for this worldview
  • Rapid Assembly
  • Some controls don't fit 100% conceptually 
  • Performance
  • Declarative things can get messy, and even harder to read if posessing any level of complexity
<doin-things
    data-ng-model="stuff"
    data-ng-mouseover="hoverEdit = true" 
    data-ng-mouseleave="hoverEdit = false"
    data-ng-class="{ 
        'hover-class': hoverEdit, 
        'btn-green-on':allOn2, 
        'btn-green-off' : !allOn2, 
         visible: isPowerUser && !disabled, 
        enabled: isAdmin,
         disabled: !isAdmin}"
    data-ng-click="var1 = (allOn2==true ? allOn2 : !allOn2)"
    data-ng-if="someCondition ? firdethisFunction(): orthisfunction()"
    data-ng-directive ="coindition && condition2 && condition3 ? 4 : functionIfire()"
    data-ng-another-directive
    data-is-this-a-directive-or-just-an-attribute-lol
    data-thenwho-was-scope
    data-ng-ng-ng-nggggggggg-nggn-ngngngngngngg
></doin-things>

React.js

  • Concerned with UI
  • (Flux is the full stack solution)
  • Implements a Virtual DOM
  • One Way Data Binding
  • Templating (if you call it that) uses JSX, and basically a preprocessor turns it into react code.
  • Component-Driven
  • Organizing Principles
    • State
    • Lifecycle
  • Whiz bang feature that basically make react do what it does.
  • requires stable unique keys on darn near everything to work well.
  • Implements diffing and prevents having to update unnecessary nodes

Implementation-wise what does this mean for you?

 

Not much, just use React and this happens automatically

 

The Virtual DOM

Thinking in State and Lifecycle

(isnt new)

;(function ( $, window, document, undefined ) {
    $.widget( "namespace.widgetName" , {
        options: {
            someValue: null
        },
        _create: function () {
            this.element.addStuff();
        },
        destroy: function () {
            $.Widget.prototype.destroy.call(this);
        },
        _privateMethod: function ( event ) {
            console.log("_privateMethodcalled");
        },
        method: function ( event ) {
            this._trigger("dataChanged", event, {
                key: "someValue"
            });
        },
        _setOption: function ( key, value ) {
            switch (key) {
            case "someValue":
                //this.options.someValue = doSomethingWith( value );
                break;
            default:
                //this.options[ key ] = value;
                break;
            }
            $.Widget.prototype._setOption.apply( this, arguments );
        }
    });
})( jQuery, window, document );

State

and

Lifecycle

in

jQuery UI

AnguledditComponents.Test = React.createClass({
    displayName: 'test-component',
    propTypes: {
        optionalArray: React.PropTypes.array,
        optionalBool: React.PropTypes.bool,
        value: React.PropTypes.string.isRequired
    },
    mixins: [someMixin, anotherMixin],
    //lifecyclehooks
    componentWillMount: function(){},
    componentDidMount: function(){},
    componentWillRecieveProps: function(){},
    componentWillUpdate: function(){},
    componentDidUpdate: function(){},
    componentWillUnmount: function(){},
    shouldComponentUpdate: function(){},   
    //init
    getDefaultProps: function () {
        return {
            value: 'default value'
        };
    },
    getInitialState: function () {},
    __privateFunction: function(){},
    //main entry point
    render: function render() {

        return React.DOM({
            key: 'uniquekey'
        }, 'contents');
    }
});

State

and

Lifecycle

in

REACT

Real Talk

  • React is very fast, and the virtual DOM is cool
  • Thinking of the lifecycle of a component is comfortable for high(er) complexity material
  • For application assembly, working in React can be more tedius than simply declaring html
  • JSX is kind of a drag, and including html strings in your javascript is too. You'll need to set up preprocessors to get work done. 

 

  •  
  • JSX can feel disconnected to whats actually happening. basically craps out a ton of nested functions.
  • Sometimes the Virtual DOM feels like a minor step above string concatination, and below templating.
  • One way binding is very easy to predict, and  like angular is perfectly testable.
  • Some levels of an application are better candidates for this approach than others.
var HelloMessage = React.createClass({
  render: function() {
    return <div>Hello {this.props.name}</div>;
  }
});

 

Maybe we could use them together to leverage the mutual advantages of each?

They both have strengths.

Now lets look at some fabulous code

(for fabulous people)

git clone git@github.com:the-simian/OKCJS-December-2014-Angular-and-React.git
npm install
bower install
grunt serve

Conclusions

  • Ignore the vitriol of the framework debates
  • Draw from the wisdom of past frameworks, and map them to what you're using now.
  • Think about your usecase
    • performance
    • personnel
    • workflow
    • comfort-zone
  • Understand The "Worldview" of a Tool (and its limitations)
  • Consider the level and cost of any tool or abstraction

I get to pull it all together here.

Now we get to chat.

Questions.

Discussion.

Tales of Triumph™

Synergy

jesseharlin.net

@5imian