An Introduction to React.JS

Dave's Favourite JS Framework

Goals

  • Explain concepts of React.JS (with examples)
  • Make fun of Ted

What is React.JS?

  • Javascript framework for constructing the DOM, written by Facebook
  • "The V in MVC"
  • Known for being very fast for interactive web pages
  • Controversial
  • Also a framework for writing native iOS apps: "Learn once, write anywhere" (Android support coming later)

Features in React.JS

  • The Virtual DOM -- only updates things that have changed
  • Both server and client side rendering (w/ node.js)
  • Markup a page in static HTML, make interactive by decomposing the page into a series of components

Competitors

  • Angular
  • Mustache/Handlebars/Smarty/ERB/other templating languages (Remember: the "V" in MVC, not "An MVC framework")

Thinking in React

  • See talk: "Rethinking Best Practices"
  • Composition over inheritance (like the GUI version of functional programming)
  • Components have "state" (mutable) and "properties" (immutable)
  • State should only exist in one place, be passed down to subcomponents as properties

Example

Example

Example 2

Example 2

Apologies for the bad graphics

Example 2

Black
Filter Component
Green
Header Component
Cyan
Filter Item Component
Yellow
Action List Component
Orange
Action Button Component

Some Simplified Bootstrap Markup

(Only contains header and first row)

((Fits on a slide but has enough to demo power of React))

<div class="row">
    <h2>Selection Filter</h2>
    <div class="row">
        <div class="col-md-4">Site:</div>
        <div class="col-md-4"><select>...</select></div>
        <div class="col-md-4">DCCID:</div>
        <div class="col-md-4"><input type="text" /></div>
    </div>
</div>

Some XML Markup

<SelectionFilter Title="Selection Filter">
    <Filter Name="Site" Options=... />
    <Filter Name="DCCID"  />
    <Filter Name="Subproject" Options=... />
    <Filter Name="PSCID"  />
</SelectionFilter>
                    

In React (First Pass)

FilterComponent = React.createClass({
    render: function() {
        return (
            <div className="row">
                <h2>Selection Filter</h2>
                <div className="row">
                    <div className="col-md-4">Site:</div>
                    <div className="col-md-4"><select>...</select></div>
                    <div className="col-md-4">DCCID:</div>
                    <div className="col-md-4"><input type="text" /></div>
                </div>
            </div>
        );
    }
});
React.render("pageDiv", <FilterComponent />);
                    

In React (Transpiled)

FilterComponent = React.createClass({displayName: 'FilterComponent',
    render: function() {
        return (
            React.createElement("div", {className: "row"},
                React.createElement("h2", null, "Selection Filter"),
                React.createElement("div", {className: "row"},
                    React.createElement("div", {className: "col-md-4"}, "Site:"),
                    React.createElement("div", {className: "col-md-4"}, React.createElement("select", null, "...")),
                    React.createElement("div", {className: "col-md-4"}, "DCCID:"),
                    React.createElement("div", {className: "col-md-4"}, React.createElement("input", {type: "text"}))
                )
            )
        );
    }
});
React.render("pageDiv", React.createElement(FilterComponent, null));

In React (With Title Property)

FilterComponent = React.createClass({
    render: function() {
        return (
            <div className="row">
                <h2>{this.props.Title}</h2>
                <div className="row">
                    <div className="col-md-4">Site:</div>
                    <div className="col-md-4"><select>...</select></div>
                    <div className="col-md-4">DCCID:</div>
                    <div className="col-md-4"><input type="text" /></div>
                </div>
            </div>
            );
        }
});
React.render("pageDiv", <FilterComponent Title="Selection Filter"/>);

In React (With Subcomponents)

FilterComponent = React.createClass({
        render: function() {
            return (
                <div className="row">
                    <h2>{this.props.Title}</h2>
                    <div className="row">
                        <SiteFilterComponent />
                        <CandidateFilterComponent />
                    </div>
                </div>
                            );
        }
});
SiteFilterComponent = React.createClass({
    render: function() {
        return (
            <div>
                <div className="col-md-4">Site:</div>
                <div className="col-md-4"><select>...</select></div>
            </div>
        );
    }
});
CandidateFilterComponent = React.createClass({
    render: function() {
        return (
            <div>
                <div className="col-md-4">DCCID:</div>
                <div className="col-md-4"><input type="text" /></div>
            </div>
        );
    }
});
React.render("pageDiv", <FilterComponent Title="Selection Filter"/>);

Why are Site and Candidate so specific??

SelectFilterComponent = React.createClass({
    render: function() {
        return (
            <div>
                <div className="col-md-4">{this.props.Label}:</div>
                <div className="col-md-4"><select>{this.props.Options}</select></div>
            </div>
        );
    }
});
SiteFilterComponent = React.createClass({
    render: function() {
        return <SelectFilterComponent Label="Site" Options="..."/>
    }
});

                        

Can we get more generic?

Yes, with children

FilterComponent = React.createClass({
        render: function() {
            return (
                <div className="row">
                    <h2>{this.props.Title}</h2>
                    <div className="row">
                        {this.props.children}
                    </div>
                </div>
                            );
        }
});
/* <...stuff from previous slides here...> */
React.render("pageDiv",
<FilterComponent Title="Selection Filter">
    <SelectFilterComponent Label="Site" Options=... />
    <TextFilterComponent Label="DCCID"  />
    <SelectFilterComponent Label="Subproject" Options=... />
    <TextFilterComponent Label="PSCID"  />
</FilterComponent/>
);

So what about state (and interactions?)

Header toggle?

Add a "collapsed" state

FilterComponent = React.createClass({
        getInitialState: function() {
            return {
                "collapsed" : false
            };
        },
        toggleHeader: function() {
            var oldState = this.state.collapsed;
            this.setState({
                "collapsed" : !oldState
            });
            if (this.props.onHeaderToggle) {
                this.props.onHeaderToggle();
            }
        },
        render: function() { /* render method goes here */ }
        }
});

Update Render Method to handle collapsed state

render: function() {
    if (this.state.collapsed) {
        return (<div className="row">
                    <h2>{this.props.Title}</h2>
               </div>);
    }
    return (
        <div className="row">
            <h2>{this.props.Title}</h2>
            <div className="row">
                {this.props.children}
            </div>
        </div>
        );
    }
}

Add interactivity

render: function() {
    if(this.state.collapsed) {
        return (<div className="row">
                    <h2 onClick={this.toggleHeader}>{this.props.Title}</h2>
               </div>);
    }
    return (
        <div className="row">
            <h2 onClick={this.toggleHeader}>{this.props.Title}</h2>
            <div className="row">
                {this.props.children}
            </div>
        </div>
        );
    }
}

Review

  1. Started with static bootstrap markup.
  2. Progressively decomposed into components.
  3. Made components reuseable with properties (the result was more semanticly meaningful than the original markup.)
  4. Added interactivity with state.
  5. Now we have a generic (toggleable) Filter component, TextFilter and SelectFilter subcomponents that can be reused on any of other page.
  6. Ted has silly hair.

Thinking in React, Again

Composition over Inheritance

Separation of concerns, not technologies

Thanks for your time