Building an ES6/JSX/React/Flux App – Part 3 – Authentication

Over the last two posts, I’ve delved into React and built my own Flux Light Architecture, all the while trying to implement the most basic of tutorials – a two-page application with client-side routing and remote data access. It’s now time to turn my attention to authentication. I’m – as ever – going to use my favorite authentication service, Auth0. Let’s first of all get authentication working, then work on how to use it.

New Actions

I need two new actions – one for logging in and one for logging out – to support authentication. This is defined in actions.js like this:

    static login(token, profile) {
        dispatcher.dispatch('LOGIN', { authToken: token, authProfile: profile });
    }

    static logout() {
        dispatcher.dispatch('LOGOUT');
    }

The Auth0 system returns a JSON Web Token and a profile object when you log in to it. These are passed along for storage into the store.

Store Adjustments

I’ve created a pair of new actions that carry data, so I need somewhere to store them. That’s done in the stores/AppStore.js file. First off, I need to initialize the data within the constructor:

    constructor() {
        super('AppStore');
        this.logger.debug('Initializing AppStore');

        this.initialize('pages', [
          { name: 'welcome', title: 'Welcome', nav: true, auth: false, default: true },
          { name: 'flickr', title: 'Flickr', nav: true, auth: false },
          { name: 'spells', title: 'Spells', nav: true, auth: true }
        ]);
        this.initialize('route', this.getNavigationRoute(window.location.hash.substr(1)));
        this.initialize('images', []);
        this.initialize('lastFlickrRequest', 0);
        this.initialize('authToken', null);
        this.initialize('authProfile', null);
    }

I also need to process the two actions – this is done in the onAction() method:

            case 'LOGIN':
                if (this.get('authToken') != null) {
                    this.logger.error('Received LOGIN action, but already logged in');
                    return;
                }
                if (data.authToken == null || data.authProfile == null) {
                    this.logger.errro('Received LOGIN action with null in the data');
                    return;
                }
                this.logger.info(`Logging in with token=${data.authToken}`);
                this.set('authToken', data.authToken, true);
                this.set('authProfile', data.authProfile, true);
                this.changeStore();
                break;

            case 'LOGOUT':
                if (this.get('authToken') == null) {
                    this.logger.error('Received LOGOUT action, but not logged in');
                    return;
                }
                this.logger.info(`Logging out`);
                this.set('authToken', null, true);
                this.set('authProfile', null, true);
                this.changeStore();
                break;

Both action processors take care to ensure they are receiving the right data and that the store is in the appropriate state for the action before executing it.

The UI

There were three places I needed work. The first was in the NavBar.jsx file to bring in a NavToolbar.jsx component:

import React from 'react';
import NavBrand from './NavBrand.jsx';
import NavLinks from './NavLinks.jsx';
import NavToolbar from './NavToolbar.jsx';

class NavBar extends React.Component {
    render() {
        return (
            <header>
                <div className="_navbar">
                    <NavBrand/>
                </div>
                <div className="_navbar _navbar_grow">
                    <NavLinks pages={this.props.pages} route={this.props.route}/>
                </div>
                <div className="_navbar">
                    <NavToolbar/>
                </div>
            </header>
        );
    }
}

The second was the Client/views/NavToolbar.jsx component – a new component that provides a toolbar on the right side of the navbar:

import React from 'react';
import Authenticator from './Authenticator.jsx';

class NavToolbar extends React.Component {
    render() {
        return (
          <div className="_navtoolbar">
            <ul>
              <li><Authenticator/></li>
            </ul>
          </div>
      );
    }
}

export default NavToolbar;

Finally, I needed the Client/views/Authenticator.jsx component. This is a Controller-View style component. I’m using the Auth0Lock library, which can be brought in through dependencies in package.json:

  "dependencies": {
    "auth0-lock": "^7.6.2",
    "jquery": "^2.1.4",
    "lodash": "^3.10.0",
    "react": "^0.13.3"
  },

You should also add brfs, ejsify and packageify to the devDependencies, per the Auth0 documentation. Here is the top of the Client/views/Authenticator.jsx file:

import React from 'react';
import Auth0Lock from 'auth0-lock';
import Logger from '../lib/Logger';
import Actions from '../actions';
import appStore from '../stores/AppStore';

class Authenticator extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            token: null
        };
        this.logger = new Logger('Authenticator');
    }

    componentWillMount() {
        this.lock = new Auth0Lock('YOUR-CLIENT-ID', 'YOUR-DOMAIN.auth0.com');
        this.appStoreId = appStore.registerView(() => { this.updateState(); });
        this.updateState();
    }

    componentWillUnmount() {
        appStore.deregisterView(this.appStoreId);
    }

    updateState() {
        this.setState({
            token: appStore.get('authToken')
        });
    }

I don’t like having the client ID and domain embedded in the file, so I’m going to introduce a local WebAPI to solve that. Ensure you swap in your own Auth0 settings here. Other than that minor change, this is the basic Controller-View pattern. Now for the rendering:

    onClick() {
        if (this.state.token != null) {
            Actions.logout();       // Generate the logout action - we will be refreshed
            return;
        }

        this.lock.show((err, profile, token) => {
            this.lock.hide();
            if (err) {
                this.logger.error(`Error in Authentication: `, err);
                return;
            }
            Actions.login(token, profile);
        });
    }

    render() {
        let icon = (this.state.token == null) ? 'fa fa-sign-in' : 'fa fa-sign-out';
        let handler = event => { return this.onClick(event); };

        return (
            <span className="_authenticator" onClick={handler}>
                <i className={icon}></i>
            </span>
        );
    }

The render() method registers a click handler (the onClick() method) and then sets the icon that is displayed based on whether the current state is signed in or signed out. The onClick() method above it handles showing the lock. Once the response is received from the Auth0 system, I initiate an action to log the user in. If the user was logged in, the click initiates the logout action.

There is a methodology (redirect mode in Auth0 lock) that allows you to show the lock, then the page will be refreshed with a new hash containing the token. You can then store the token and restore the original page. That is all sorts of ugly to implement and follow. I like this version for it’s simplicity. I store the state and values of the authentication in the store, use actions to store that data, but don’t refresh the page.

Checking Authentication

I have a page within this app right now that requires authentication called spells. It never gets displayed because the code in NavLinks.jsx has logic to prevent it. Let’s fix that now.

First, NavLinks.jsx needs a new boolean property called authenticated:

NavLinks.propTypes = {
    authenticated: React.PropTypes.bool.isRequired,
    pages: React.PropTypes.arrayOf(
            React.PropTypes.shape({
                auth: React.PropTypes.bool,
                nav: React.PropTypes.bool,
                name: React.PropTypes.string.isRequired,
                title: React.PropTypes.string.isRequired
            })
        ).isRequired,
    route: React.PropTypes.string.isRequired
};

I can also change the logic within the visibleLinks to check the authenticated property:

        let visibleLinks = this.props.pages.filter(page => {
            if (this.props.authenticated === true) {
                return (page.nav === true);
            } else {
                return (page.nav === true && page.auth === false);
            }
        });

Now, I need to ensure that the NavBar and the AppView bubble the authentication state down the tree of components. That means adding the authenticated property to NavBar (I’ll leave that to you – it’s in the repository) and including it in the NavLinks call:

<NavLinks pages={this.props.pages} route={this.props.route} authenticated={this.props.authenticated}/>

That also means, AppView.jsx must provide it to the NavBar. This is a little more extensive. First of all, I’ve updated the state in the constructor to include an authenticated property:

        this.state = {
            pages: [],
            route: 'welcome',
            authenticated: false
        };

That means updateState() must be updated to account for the new state variable:

    updateState() {
        let token = appStore.get('authToken');
        this.setState({
            route: appStore.get('route'),
            pages: appStore.get('pages'),
            authenticated: token != null
        });
    }

Finally, I can push this state down to the NavBar:

        return (
            <div id="pagehost">
                <NavBar pages={this.state.pages} route={this.state.route} authenticated={this.state.authenticated}/>
                <Route/>
            </div>
        );

With this code, the Spells link will only appear when the user is authenticated.

Requesting API Data

So far, I’ve created an application that can re-jig itself based on the authentication state. But it’s all stored on the client. The authentication state is only useful if you request data from a remote server. I happen to have a Web API called /api/spells that must be used with a valid Auth0 token. You can read about it in a prior post. I’m not going to cover it here. Suffice to say, I can’t get data from that API without submitting a proper Auth0 JWT token. The code in the repository uses User Secrets to store the actual secret for the Auth0 JWT that is required to decode. If you are using the RTM version of Visual Studio 2015, right click on the project and select Manage User Secrets. Your user secrets should look something like this:

{
  "JWT": {
    "Domain": "YOUR-DOMAIN.auth0.com",
    "ClientID": "YOUR-CLIENT-ID",
    "ClientSecret": "YOUR-CLIENT-SECRET"
  }
}

If you run the application and browse to /api/settings, you should see the Domain and ClientID. If you browse to /api/spells, you should get a 401 response.

I can now use the same technique I used when requesting the Flickr data. Firstly, create two actions – one for the request and one for the response (in actions.js):

    static requestSpellsData() {
        dispatcher.dispatch('REQUEST-AUTHENTICATED-API', {
            api: '/api/spells',
            callback: Actions.processSpellsData
        });
    }

    static processSpellsData(data) {
        dispatcher.dispatch('PROCESS-SPELLS-DATA', data);
    }

Then, alter the Store to handle the request and response. This is a place where the request may be handled in one store and the response could be handled in a different store. I have a generic action that says “call an API with authentication”. It then sends the data to whatever action I tell it to. If I had a “SpellsStore”, the spells store could process the spells data on the return. It’s this disjoint method of handling the API call and response that allows me to have stores that don’t depend on one another. I’ve added the following to the constructor of the stores/AppStore.js:

this.initialize('spells', []);

I’ve also added the following to the case statement in onAction():

            case 'REQUEST-AUTHENTICATED-API':
                if (this.get('authToken') == null) {
                    this.logger.error('Received REQUEST-AUTHENTICATED-API without authentication');
                    return;
                }
                let token = this.get('authToken');
                $.ajax({
                    url: data.api,
                    dataType: 'json',
                    headers: { 'Authorization': `Bearer ${token}` }
                }).done(response => {
                    data.callback(response);
                });

            case 'PROCESS-SPELLS-DATA':
                this.logger.info('Received Spells Data: ', data);
                this.set('spells', data);

Finally, I can adjust the views/Spells.jsx file to be converted to a Controller-View and request the data. I’ve already done this for the views/Flickr.jsx. You can check out my work on the GitHub repository.

I’ve done something similar with the Settings API. The request doesn’t require authentication, so I just process it. I also cache the results (if the settings have been received, I don’t need to ask them again). This data is stored as ‘authSettings’ in the store. I then added the authSettings to the state in the views/Authenticator.jsx component. I also need to trigger the settings grab – I do this in the views/Authenticator.jsx component via the componentWillMount() method:

    componentWillMount() {
        if (this.lock == null && this.state.settings != null) {
            this.lock = new Auth0Lock(this.state.settings.ClientID, this.state.settings.Domain);
        } else {
            Actions.requestSettingsData();
        }
        this.appStoreId = appStore.registerView(() => { this.updateState(); });
        this.updateState();
    }

I don’t want the authenticator to be clickable until the settings have been rendered, so I added the following to the top of the render() method:

    render() {
        // Additional code for the spinner while the settings are loaded
        if (this.state.settings == null) {
            return (
                <span className="_authenticator">
                    <i className="fa fa-spinner fa-pulse"></i>
                </span>
            );
        }

This puts a spinner in the place of the login/logout icon until the settings are received.

Wrap-up

One of the biggest differences between MVC and Flux is the data flow. In the MVC architecture, you have a Datastore object that issues the requests to the backend and somehow updates the model, that then informs the controller via a callback (since it’s async). It feels hacky. MVC really works well when the controller can just do the request to get the model from the data store and get the response back to feed the view. Flux feels right in the async front-end development world – much more so than the MVC model.

The Flux architecture provides for a better flow of data and allows the easy integration of caching algorithms that are right for the environment. If you want to cache across restarts of the application (aka page refreshes), then you can store the data into localStore. If you want to specify a server-side refresh (for example, for alerting), then you can integrate SignalR into the system and let SignalR generate the action.

As you can guess, I’m loving the Flux architecture. After getting my head around the flow of data, it became very easy to understand. Code you understand is much easier to debug.

As always, you can get my code on my GitHub Repository.

Building an ES6/JSX/React Flux App – Part 2 – The Flux

In the first part of this tutorial, I concentrated on React views. In fact, I didn’t do anything else. Except for a little bit of in-component interactivity, everything that resulted from those views was static DOM. I could have written a little bit of JavaScript inside the HTML page to get the same effect. Smaller applications like these seem to make the frameworks cumbersome, but they demonstrate core features in an isolated setting. React and Flux (and pretty much any other architecture, framework or library) really come into their own in larger applications.

The same is true of Flux. Flux is the architecture that goes along with React. It does the same job as MVC – an interactive page – but in a very different way. Flux is definitely not MVC, as you can see from the architecture diagram:

08192015-1

In a Flux architecture, the Dispatcher is a central co-ordination point. It receives actions and dispatches them to stores. Stores react to those actions, adjusting their data, before informing any dependent views of a change. The actions can come from anywhere – external events like AJAX loads as well as user events like clicks or changes.

Normally, I would go to a library to implement such an architecture. If I were in an MVC world, I would be getting AngularJS or EmberJS to assist. There are lots of libraries out there (Fluxxor, Reflux and Alt to name a few). They all implement the full Flux architecture, have great tutorials in written and video form and are full featured. However, I found them difficult to wrap my head around. That’s mostly because I was wrapping my head around Flux – the design pattern – and their library at the same time. I’m more interested in the design pattern.

So I wrote my own. I’m calling this “Flux Light”. It doesn’t implement some of the more cumbersome features of Flux. It’s written entirely in ES6 and it’s opinionated. It expects you to write your code in ES6 as well. It also expects no overlapping stores (i.e. one store does not depend on another). It expects to be bundled with browserify or similar. I make no apologies for this. It’s a learning exercise and nothing more. (Of course, if folks feel that it’s useful to them, let me know and I will publish it on npm). The code for the library is located in Client/lib in the repository. I’m going to show how to use it.

The Dispatcher

The Dispatcher is the center of the Flux architecture. It has a couple of requirements:

  • Components should be able to use dispatch() with an Action
  • Stores should be able to register for actions

All actions flow through the Dispatcher, so it’s code surface should be small and simple. This code is located in lib/Dispatcher.js. That is only the class though. You will want to initialize the dispatcher. Do this in Client/dispatcher.js like this:

import Dispatcher from './lib/Dispatcher';

var dispatcher = new Dispatcher({
  logLevel: 'ALL'
});

export default dispatcher;

The only options available are logging ones right now. I use the logLevel to set the minimal log level you want to see in the JavaScript console. The most common log levels will be ‘ALL’ or ‘OFF’. If you don’t specify anything, you will get errors only.

Actions

Actions are just calls into the dispatcher dispatch() method. I’ve got a class full of static methods to implement actions, located in Client/actions.js, like so:

import dispatcher from './dispatcher';

export default class Actions {
    static navigate(newRoute) {
        dispatcher.dispatch('NAVIGATE', { location: newRoute });
    }
}

I can use this class to generate actions. For example, I want to have the NAVIGATE action happen when I click on one of the navigation links. I can adjust the NavLinks.jsx file like this:

import React from 'react';
import Actions from '../actions';

class NavLinks extends React.Component {
    onClick(route) {
        Actions.navigate(route);
    }

    render() {
        let visibleLinks = this.props.pages.filter(page => {
            return (page.nav === true && page.auth === false);
        });
        let linkComponents = visibleLinks.map(page => {
            let cssClass = (page.name === this.props.route) ? 'link active' : 'link';
            let handler = event => { return this.onClick(page.name, event); };

            return (<li className={cssClass} key={page.name} onClick={handler}>{page.title}</li>);
            });

        return (
            <div className="_navlinks">
                <ul>{linkComponents}</ul>
            </div>
        );
    }
}

Here I tie the onClick method via an event handler to the click event on the link. That, in turn, issues a navigate action to the dispatcher via the Actions class.

Somewhere, I have to bootstrap the dispatcher. That’s done in the app.jsx file:

import React from 'react';
import dispatcher from './dispatcher';
import AppView from './views/AppView.jsx';

dispatcher.dispatch('APPINIT');

React.render(<AppView/>, document.getElementById('root'));

The AppStore

In my prior example, I was passing the pages and route down from the bootstrap app.jsx file. I’m now going to store that information in a Store – a flux repository for data. I’ve got a nice API for this. Firstly, there is a class you can extend for most of the functionality – lib/Store. You have to implement a constructor to set the initial state of the store and an onAction() method to handle incoming actions from the dispatcher.

The API for the Store contains the following:

  • Store.initialize(key,value) initializes a key-value pair in the store.
  • Store.set(key, value, [squashEvents=false]) sets a key-value pair in the store. Normally, a store changed event will be triggered. If you set squashEvents=true, then the store changed event is squashed, allowing you to set multiple things before issuing a store changed event.
  • Store.get(key) returns the value of the key in the store.
  • Store.storeChanged() issues a store changed event.
  • Store.registerView(callback) calls the callback whenever the store is changed. Returns an ID that you can use to de-register the view.
  • Store.deregisterView(id) de-registers a prior view registration.

Creating a store is simple now. You don’t have to worry about a lot of the details. For instance, here is my store/AppStore.jsx file:

import Store from '../lib/Store';
import find from 'lodash/collection/find';
import dispatcher from '../dispatcher';

class AppStore extends Store {

    constructor() {
        super('AppStore');
        this.logger.debug('Initializing AppStore');

        this.initialize('pages', [
          { name: 'welcome', title: 'Welcome', nav: true, auth: false, default: true },
          { name: 'flickr', title: 'Flickr', nav: true, auth: false },
          { name: 'spells', title: 'Spells', nav: true, auth: true }
        ]);
        this.initialize('route', this.getNavigationRoute(window.location.hash.substr(1)));
    }

    onAction(actionType, data) {
        this.logger.debug(`Received Action ${actionType} with data`, data);
        switch (actionType) {

            case 'NAVIGATE':
                let newRoute = this.getNavigationRoute(data.location);
                if (newRoute !== this.get('route')) {
                    this.set('route', newRoute);
                    window.location.hash = `#${newRoute}`;
                }
                break;

            default:
                this.logger.debug('Unknown actionType for this store - ignoring');
                break;
        }
    }

    getNavigationRoute(route) {
        let newRoute = find(this.get('pages'), path => { return path.name === route.toLowerCase(); });
        if (!newRoute) {
            newRoute = find(this.get('pages'), path => { return path.default && path.default === true; });
        }
        return newRoute.name || '';
    }
}

var appStore = new AppStore();
dispatcher.registerStore(appStore);

export default appStore;

The constructor uses initialize() to initialize two data blocks – the pages and the route from the original app.jsx. The onAction() method listens for NAVIGATE actions and acts accordingly.

At the end, I create a singleton version of the AppStore and register it with the dispatcher – this causes the dispatcher to send actions to this store.

The Controller-View

In the Flux architecture, there are two types of React components. Controller-Views are linked to one or more stores and use state to maintain and update their children. Other React components are not linked to stores and DO NOT USE STATE – they only use props.

Controller-Views need to do the following:

  • Call registerView on each store they are associated with when the component is mounted (use the componentWillMount() lifecycle method)
  • Call deregisterView on each store they are associated with when the component is about to be unmounted (use the componentWillUnmount() lifecycle method)

In my previous post, I created an AppView.jsx to use state with the start of a router. I can alter that to become a Controller-View:

import React from 'react';
import appStore from '../stores/AppStore';
import NavBar from '../views/NavBar';
import Welcome from '../views/Welcome';
import Flickr from '../views/Flickr';
import Spells from '../views/Spells';

class AppView extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            pages: [],
            route: 'welcome'
        };
    }

    componentWillMount() {
        this.appStoreId = appStore.registerView(() => { this.updateState(); });
        this.updateState();
    }

    componentWillUnmount() {
        appStore.deregisterView(this.appStoreId);
    }

    updateState() {
        this.setState({
            route: appStore.get('route'),
            pages: appStore.get('pages')
        });
    }

    render() {
        let Route;
        switch (this.state.route) {
            case 'welcome': Route = Welcome; break;
            case 'flickr': Route = Flickr; break;
            case 'spells': Route = Spells; break;
            default: Route = Welcome;
        }

        return (
            <div id="pagehost">
                <NavBar pages={this.state.pages} route={this.state.route}/>
                <Route/>
            </div>
        );
    }
}

export default AppView;

The constructor just sets some empty state variables. When the component is mounted, the view is registered with the store and the state is updated from the store. When the component is unmounted (or just before), the view is deregistered again. The function updateState() is the callback that the store uses to inform the view of an updated state.

In the render() function, I’ve expanded the number of routes to the full complement. This also matches the list defined in the AppStore. If you wanted to keep the definition of the pages in one place, you could issue an action from this component to set the pages, then let the state update them once they’ve gone through the system. You would not want to just set the pages within the store. That would most definitely not be flux-like.

To round out this sequence, I’ve added a couple of pages – Flickr.jsx and Spells.jsx – as simple static React components. You can get this code drop from my GitHub Repository.

Handling AJAX in a Flux Architecture

Let’s say I wanted to fill in the details of the Flickr page. This is designed to bring the first 20 images for a specific tag back to the page. To do that, I need to make an AJAX JSONP request to the Flickr API.

In a React world, I will do two actions. The first will be when the Flickr page comes into focus. I want to issue a “REQUEST-FLICKR-DATA” action at that point. This will cause the store to kick off the AJAX request. When the request comes back, the store will issue a “PROCESS-FLICKR-DATA” action with the data that came back. This ensures that all stores get notified of the AJAX request and response.

Why the store? The store is the central source of truth for all data within a Flux architecture. The views should not be requesting the data.

Why the second action? Well, in this simple application, we could use just one action – the request. However, let’s say you had another store that counted the number of in-flight AJAX requests – or one that did nothing but do AJAX requests (for example, to allow the inclusion of authentication tokens). You may have one store handling the request and one store handling the response.

To implement this, I first added the actions to my actions.js file:

import dispatcher from './dispatcher';

export default class Actions {
    static navigate(newRoute) {
        dispatcher.dispatch('NAVIGATE', { location: newRoute });
    }

    static requestFlickrData(tag) {
        dispatcher.dispatch('REQUEST-FLICKR-DATA', { tag: tag });
    }

    static processFlickrData(data) {
        dispatcher.dispatch('PROCESS-FLICKR-DATA', data);
    }
}

Then I altered the onAction() method within the stores/AppStore.js file:

            case 'REQUEST-FLICKR-DATA':
                let lastRequest = this.get('lastFlickrRequest');
                let currentTime = Date.now;
                let fiveMinutes = 5 * 60 * 1000;
                if ((currentTime - lastRequest) > fiveMinutes) {
                    return;
                }
                $.ajax({
                    url: 'http://api.flickr.com/services/feeds/photos_public.gne',
                    data: { tags: data.tag, tagmode: 'any', format: 'json' },
                    dataType: 'jsonp',
                    jsonp: 'jsoncallback'
                }).done(response => {
                    Actions.processFlickrData(response);
                });
                break;

            case 'PROCESS-FLICKR-DATA':
                this.set('images', data.items);
                break;

In this case, I only request the Flickr data if five minutes have elapsed. When the response comes back, I trigger another action. This is, in my case, processed just below the request by the PROCESS-FLICKR-DATA block. If five minutes have not elapsed, then no request is made and no changes to the page are made. You can flick back and forth between the welcome and flickr page all you want – it won’t change.

Of course, there was some setup required for this code to work:

import Store from '../lib/Store';
import find from 'lodash/collection/find';
import dispatcher from '../dispatcher';
import Actions from '../actions';
import $ from 'jquery';

class AppStore extends Store {

    constructor() {
        super('AppStore');
        this.logger.debug('Initializing AppStore');

        this.initialize('pages', [
          { name: 'welcome', title: 'Welcome', nav: true, auth: false, default: true },
          { name: 'flickr', title: 'Flickr', nav: true, auth: false },
          { name: 'spells', title: 'Spells', nav: true, auth: true }
        ]);
        this.initialize('route', this.getNavigationRoute(window.location.hash.substr(1)));
        this.initialize('images', []);
        this.initialize('lastFlickrRequest', 0);
    }

Don’t forget to add jquery to the list of dependencies in package.json or via npm install --save jquery.

Now that I have the actions and store sorted for the new data source, I can convert Flickr.jsx to a Controller-View and render the images that get loaded. I’m going to kick off the request in the constructor. Since I have a rudimentary cache going, it won’t hit the Flickr API badly. Here is the code in views/Flickr.jsx:

import React from 'react';
import Actions from '../actions';
import appStore from '../stores/AppStore';

class Flickr extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            images: [],
            tag: 'seattle'
        };

        Actions.requestFlickrData(this.state.tag);
    }

    componentWillMount() {
        this.appStoreId = appStore.registerView(() => { this.updateState(); });
        this.updateState();
    }

    componentWillUnmount() {
        appStore.deregisterView(this.appStoreId);
    }

    updateState() {
        this.setState({
            images: appStore.get('images')
        });
    }

    render() {
        let images = this.state.images.map(image => {
            let s = image.media.m.split('/');
            let fn = s[s.length - 1].split('.')[0];
            return (
                <div className="col-sm-6 col-md-3" key={fn}>
                    <a className="thumbnail"><img src={image.media.m}/></a>
                </div>
            );
        });

        return (
            <section id="flickr">
                <h2>Flickr</h2>
                <div className="row">{images}</div>
            </section>
        );
    }
}

export default Flickr;

There are a couple of things I could have done differently here. Firstly, I could have requested the flickr data only when the component was mounted. This version asks for the data when the component is created. I wanted to minimize those round trips to the Flickr API during testing and this seemed a reasonable way of doing it. Given that I have the cache functionality in the store, I could reasonably see moving the request to the componentWillMount() method.

I could have made the Flickr component just a regular component. This would have required me to change AppView so that it made the request and passed that down when the page was instantiated. I didn’t think this was a good idea. As the application expanded, I would have all sorts of extra code in the AppView. Making each “page” have state and be connected to a store seems much more reasonable to me.

Finally, I could have made the Flickr data its own store. In this application expands, you naturally want to have stores handle specific data. For instance, you might have a store that deals with “books” or “friends” or “images”. Inevitably, you will have a simple store that deals with navigation and authentication. So, yes, I see merit in creating another store called ImageStore in a larger application. It seemed overkill for this application.

You can get the code from my GitHub Repository.

Wrap Up

This is the end of the React/Flux version of the Aurelia tutorial, but not the end of my tutorial. I like to add authentication and monitoring to my applications as well, so I’ll be taking a look at those next.

This is a good time to compare for the four frameworks I have worked with. I’ve worked with Angular, Aurelia, Polymer and React/Flux now. Let’s discuss each one.

I felt Angular was heavy on the conventional use. It didn’t allow me to be free with my JavaScript. I felt that there was the Angular way and everything else was really a bad idea. Yes, it did everything I wanted, but the forklift upgrade (coming for v2.0) and the difficulty in doing basic things, not to mention the catalog of directives one must know for simple pages, meant it was heavier than I wanted to use.

Aurelia was a breath of fresh air in that respect. It worked with ES6, not against it. Everything is a class. However, the lack of data management right now, plus a relatively heavy-weight library on the download makes this a poor choice for simple applications. I suppose I could have done the same as I did here and used browserify to bundle everything together, but it isn’t easy.

Polymer is a third of a framework, in much the same way that React is a partial framework. It can’t stand alone. You need page routing and data management. These are, in the Polymer world, extra web components that you just download. Since there is no “import” system that allows for importing from standardized locations, you end up with a lot of hacking. Polymer will find a place, particularly when you consider the upcoming ES6-compatible MVC architectures like Angular-2 and Aurelia.

React/Flux is definitely focussed on large applications. Even my modest tutorial application (and not including the library code I wrote) was a significant amount of code. However, I can appreciate the flow of data and I understand that flow of data. That allows me to short-circuit the debugging process and go straight to the source of the problem. As the application grows, the heaviness of the framework coding becomes less of an issue.

I can see areas for improvement in the React/Flux code I wrote – some boilerplate that can be kicked out into classes all of their own. I like what I have here.

Mobile is another area that I am increasingly becoming interested in. With React, there is React Native – a method of using React code within an iOS application that compiles to a native iOS app. React is also much more usable in an Apache Cordova app – allowing Android and Windows Phone coverage as well. Angular works well with Apache Cordova (see the Ionic Framework). Aurelia does not work well with mobile apps yet. Polymer is “just another component”, but the polyfills that are necessary to make Polymer work on Apache Cordova are heavier than I expected.

Overall, I’ll continue watching React with great interest.

In my next post, I’ll cover authentication with my favorite authentication service – Auth0.

Building an ES6/JSX React/Flux App – Part 1 – the Views

One of the newer technologies on the JavaScript scene is Flux. It’s getting a lot of attention right now because it’s not MVC. It seems like every other framework was doing MVC or some variant thereof. Facebook (the instigators of Flux and it’s associated library – React) decided there was a better way for larger applications.

There are many articles on React and Flux – I like the introduction from Fluxxor – a library that implements the Flux architecture. However, here is the obligatory Flux architecture diagram:

08192015-1

In the Flux Architecture, there is a Dispatcher at the center of everything. The system creates Actions that are dispatched by the Dispatcher to the Stores (all the stores). Stores hold data. Not just one type of data, mind you – they could hold many types of data. The stores emit a “store changed” event when their data changes. Views listen for those changes and re-render appropriately. Those Views are inevitably React components, whose primary purpose is to minimize the DOM replacements that go on as these are slow.

In the proper Flux architecture, the Dispatcher and Stores have specific APIs and functionalities that need to be implemented. However, one can forego a lot of the code and get a much simpler (and smaller) app by simplifying and altering the API. If you use the Reflux library, for example, they forego the Dispatcher completely – insteadrelying on the actions to dispatch directly to the stores. The interesting thing about an architecture is that it is theory – the libraries implement the concrete examples.

So much for theory. I want to build an app that implements React and Flux. Before I do that, I need to know how to write React components and how to build a production workflow for an app that utilizes React. So today is all about learning the basics of React and setting up a build process.

Initializing the Project

I’m using an ASP.NET5 project for this. I could have used a Node/Express or Koa or any number of other web servers. Aside from my Web API (which comes in at the very end when I talk about authentication), I only need client-side functionality.

I’ve also added a Client directory and created an initial index.html file:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>An ES6 React/Flux Demo</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <link rel="stylesheet" href="bundle.css">
</head>
<body>
    <div id="root">... booting ...</div>
    <script src="bundle.js"></script>
</body>
</html>

I need a build system and I’m going to use Gulp as normal. I’ve added an NPM package.json file:

{
  "version": "1.0.0",
  "name": "react-demo",
  "private": true,
  "devDependencies": {
    "gulp": "^3.9.0",
    "gulp-less": "^3.0.3"
  }
}

I’ve also created a Gulpfile.js:

var gulp = require('gulp'),
    less = require('gulp-less');

var config = {
    src: './Client',
    dest: './wwwroot'
};

var files = {
    html: config.src + '/**/*.html',
    less: config.src + '/style/bundle.less'
};

gulp.task('build', ['style', 'html']);

gulp.task('html', function ()
{
    return gulp.src([files.html]).pipe(gulp.dest(config.dest));
});

gulp.task('style', function ()
{
    return gulp.src([files.less])
        .pipe(less())
        .pipe(gulp.dest(config.dest));
});

Once this was done, I bound the build task to the Before Build step in the Task Runner Explorer. Don’t worry about the bundle.js for now – I’ll get on to that later. If you run this project (just to see it working), you should get a browser window with a booting message displayed.

You can get my starting point from my GitHub Repository.

A Simple React Component

I’m going to write what is possibly the simplest react component ever. It just pushes out a HTML DOM. I’m going to use it to provide a title for my website. The file is located in Client/views/NavBrand.jsx – note the use of the JSX extension – that’s very important, as you will see in a moment. If you are using Visual Studio 2015 (and I suggest you do!), then use item template JSX File.

import React from 'react';

class NavBrand extends React.Component {
  render() {
    return (
      <div className="_navbrand">
        <div className="valign">
          React Demo
        </div>
      </div>
    );
  }
}

export default NavBrand;

This made me do a double-take when I first saw it. A JavaScript function is returning HTML. Actually, it’s not – there are some visual clues, such as using className instead of the normal class to specify the CSS class. There are other differences:

  • If you use label for="", the for becomes htmlFor
  • If you have a HTML element that is not terminated, you need to use /> (e.g. <img />)

There are also other differences, but I’ll get to them later. Unfortunately, Visual Studio 2015 still doesn’t like ES6 + JSX syntax (and it still has problems with ES6 in general). Atom is much better in this regard, so if you are following along on a Mac or using Node/Express, you may want to switch to Atom.

I’ve also got some style in Client/style/NavBrand.less and I’ve included that file in the bundle.less file. I do this for every single React component I write, so I’m not going to mention it again. Just be sure to pick up the less stylesheets from the repository.

This only defines the React component. I also need to use it. To do this, I’m going to create a Client/app.jsx file that I’ll use as a bootstrap:

import React from 'react';
import NavBrand from './views/NavBrand.jsx';

React.render(<NavBrand/>, document.getElementById('root'));

Building The System

I’ve got a lot going on here. My code is ECMAScript 6 and has JSX embedded in it. I also use modules that need to be dealt with. I could just write this for SystemJS (and I’ve blogged about that). Instead I’m going to use a production build system based on browserify. Browserify is a system for bundling all the libraries and JS code you use into one bundle file. All I have to do is load the libraries I want as dependencies in package.json and then run browserify. I still need to transform the ES6 and JSX code into ES5.1 for most browsers. Fortunately, there is a plugin called babelify that uses Babel for that purpose.

Since this is a production workflow, I want to bring eslint into the mix for pre-run checking. Eslint also has a plugin for React/JSX, so I’ll use that. It’s important to note here – Visual Studio 2015 doesn’t seem to like mixing ES6 and JSX. You get a lot of red-squiggly lines for perfectly valid code. As a result, you need eslint to ensure you don’t make syntax errors prior to publishing your code.

These are pretty much recipes, so I’m just copying from someone else (and I forget who, but everyone seems to use the same recipe). Here is the package.json:

{
  "version": "1.0.0",
  "name": "react-demo",
  "private": true,
  "devDependencies": {
    "babelify": "^6.1.3",
    "browserify": "^11.0.0",
    "eslint": "^0.24.1",
    "eslint-plugin-react": "^3.0.0",
    "gulp": "^3.9.0",
    "gulp-eslint": "^0.15.0",
    "gulp-less": "^3.0.3",
    "gulp-rename": "^1.2.2",
    "vinyl-source-stream": "^1.1.0"
  },
  "dependencies": {
    "react": "^0.13.3"
  }
}

I also need a task in the gulpfile.js:

var gulp = require('gulp'),
  browserify = require('browserify'),
  eslint = require('gulp-eslint'),
  less = require('gulp-less'),
  rename = require('gulp-rename'),
  source = require('vinyl-source-stream');

  // Previously discussed parts not included

gulp.task('bundle', [ 'eslint', 'copyhtml' ], function () {
  var bundler = browserify({
    extensions: ['.js', '.jsx'],
    transform: ['babelify'],
    debug: true
  });

  return bundler
    .add(files.entry)
    .bundle()
    .on('error', function(err) {
      console.error(err.toString());
    })
    .pipe(source(files.entry))
    .pipe(rename('bundle.js'))
    .pipe(gulp.dest(config.dest));
});

I also need an .eslintrc file with the following contents (just create a JSON file with the name .eslintrc):

{
  "ecmaFeatures": {
    "modules": true,
    "jsx": true
  },
  "env": {
    "browser": true,
    "es6": true
  },
  "plugins": [
    "react"
  ],
  "rules": {
    "quotes": [ 2, "single", "avoid-escape" ],
    "react/display-name": [ 1, { "acceptTranspilerName": true }],
    "react/jsx-boolean-value": 1,
    "react/jsx-no-undef": 1,
    "react/jsx-quotes": 1,
    "react/jsx-sort-prop-types": 1,
    "react/jsx-sort-props": 0,
    "react/jsx-uses-react": 1,
    "react/jsx-uses-vars": 1,
    "react/no-danger": 1,
    "react/no-did-mount-set-state": 1,
    "react/no-did-update-set-state": 1,
    "react/no-multi-comp": 1,
    "react/no-unknown-property": 1,
    "react/prop-types": 1,
    "react/react-in-jsx-scope": 1,
    "react/require-extension": 1,
    "react/self-closing-comp": 1,
    "react/sort-comp": 1,
    "react/wrap-multilines": 1
  }
}

The majority of the rules are ripped from an example in the eslint-plugin-react documentation. I’ve made some changes to suit my coding style and to support ES6.

Running the project will give you a simple piece of text. You no longer have the booting message. Instead you have a React Demo statement. That’s coming from the simple component I developed earlier.

You can get the build system plus this first component from my GitHub Repository.

React Components inside React Components

React is like many other web component technologies. You can embed components inside of components. For example, let’s say I want a NavBar.jsx component:

import React from 'react';
import NavBrand from './NavBrand.jsx';

class NavBar extends React.Component {
    render() {
        return (
            <header>
                <div className="_navbar">
                    <NavBrand/>
                </div>
                <div className="_navbar _navbar_grow">

                </div>
                <div className="_navbar">

                </div>
            </header>
        );
    }
}

export default NavBar;

I’m leaving two of the DIV elements blank, for later expansion. You can clearly see the NavBrand element embedded inside of the JSX that I am returned for the NavBar element. You can adjust the app.jsx file to bring in this component instead of NavBrand to see it in action. You can, of course, get the code from my GitHub Repository.

Reusable Components – Props

Let’s say I have a set of links I want to display. The links are defined (in app.jsx) like this:

var pages = [
      { name: 'welcome', title: 'Welcome', nav: true, auth: false, default: true },
      { name: 'flickr', title: 'Flickr', nav: true, auth: false },
      { name: 'spells', title: 'Spells', nav: true, auth: true }
];
var route = 'welcome';

I could then pass these variables down into a component like this (also in app.jsx):

React.render(<NavBar pages={pages} route={route}/>, document.getElementById('root'));

These are Properties and they appear in this.props in a React component. I need to adjust my NavBar.jsx file to account for these:

import React from 'react';
import NavBrand from './NavBrand.jsx';
import NavLinks from './NavLinks.jsx';

class NavBar extends React.Component {
    render() {
        return (
            <header>
                <div className="_navbar">
                    <NavBrand/>
                </div>
                <div className="_navbar _navbar_grow">
                    <NavLinks pages={this.props.pages} route={this.props.route}/>
                </div>
                <div className="_navbar">

                </div>
            </header>
        );
    }
}

export default NavBar;

I’ve added a new component called NavLinks that takes the properties that NavBar received. Now I need to write Client/views/NavLinks.jsx:

import React from 'react';

class NavLinks extends React.Component {
    render() {
        let visibleLinks = this.props.pages.filter(page => {
            return (page.nav === true && path.auth === false);
        });
        let linkComponents = visibleLinks.map(page => {
            let cssClass = (page.name === this.props.route) ? 'link active' : 'link';
            return (<li className={cssClass} key={page.name}>{page.title}</li>);
        });

        return (
            <div className="_navlinks">
                <ul>{linkComponents}</ul>
            </div>
        );
    }
}

export default NavLinks;

A few notes here. You can use any variable within JSX – just include it in curly braces. Note how I do iteration here – Aurelia has repeat.for, Angular has ng-repeat. React just uses JavaScript so I don’t have to learn a whole bunch of new syntax, nor do I need an extra plug-in just to iterate. I do, however, need to ensure I define a key on iterated elements. Normally, React will define a default key on all elements so that it can refer to a specific key. In the case of iterators, it can’t, so you have to do it instead.

If you build and run this project, you will get a nice list of all the pages that don’t require authentication, according to the object we pass into the root element (the NavBar in app.jsx). However, you will also note that there are errors from eslint:

08152015-1

React expects you to define the types of properties that a component can accept. The route property is a string and the pages property is a complex object. To define the property, you need to add a static object called propTypes to the class. PropTypes defines the shape of the properties that you accept. This is the way I do it:


NavLinks.propTypes = {
    pages: React.PropTypes.arrayOf(
            React.PropTypes.shape({
                auth: React.PropTypes.bool,
                nav: React.PropTypes.bool,
                name: React.PropTypes.string.isRequired,
                title: React.PropTypes.string.isRequired
            })
        ).isRequired,
    route: React.PropTypes.string.isRequired
};

Put this block right above the export statement. You can do all sorts of validation and be very prescriptive with the shape of the properties coming in. Check out the docs for the full syntax.

Since the properties for NavBar are identical to the properties for NavLinks, you can cut and paste the object to the NavBar object as well to get rid of the warnings. The code, in case you got lost, is on my GitHub Repository.

State and the Welcome Page

In the Aurelia tutorial there was a Welcome page with a form and some dynamic elements. I’m going to create two things. Firstly, I’m going to create an AppView.jsx component that represents the complete page. Here is the code:

import React from 'react';
import assign from 'lodash/object/assign';
import NavBar from '../views/NavBar';
import Welcome from '../views/Welcome';

class AppView extends React.Component {
    constructor(props) {
        super(props);

        this.state = this.props;
    }

    render() {
        let Route;
        switch (this.state.route) {
            case 'welcome': Route = Welcome; break;
            default: Route = Welcome;
        }

        return (
            <div id="pagehost">
                <NavBar pages={this.state.pages} route={this.state.route}/>
                <Route/>
            </div>
        );
    }
}

AppView.propTypes = {
    pages: React.PropTypes.arrayOf(
            React.PropTypes.shape({
                auth: React.PropTypes.bool,
                nav: React.PropTypes.bool,
                name: React.PropTypes.string.isRequired,
                title: React.PropTypes.string.isRequired
            })
        ).isRequired,
    route: React.PropTypes.string.isRequired
};

export default AppView;

Don’t forget to also alter app.jsx to render the AppView instead of the NavBar. In order to compile this, I’m using a lodash function to provide a basic object deep-copy capability, so I need to my list of dependencies in package.json. Lodash is a collection of utility functions. The assign function just copies my properties into a new thing called state.

Aside from the state thing, I’m setting this up to be a router for my page – as can be seen in the render() method. I only have one route right now, but I can add more routes as they become available.

So, why two areas to store data? Properties are defined to be immutable – you set them once and walk away. They don’t get changed within the component. State can be changed. This means I can use it to cause changes in the rendered component. Obviously, the example above (while relevant later on) is a totally useless change. I’m using state instead of props – big deal.

However, if you remember the Welcome Page from the Aurelia Tutorial, you will know we need interactivity for the page. Here is the code for Welcome.jsx:

import React from 'react';

class Welcome extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            firstname: 'John',
            lastname: 'Doe'
        };
    }

    onSubmit() {
        alert(`Hello ${this.fullname}`); // eslint-disable-line no-alert
    }

    onChange() {
        this.setState({
            firstname: React.findDOMNode(this.refs.fn).value,
            lastname: React.findDOMNode(this.refs.ln).value
        });
    }

    get fullname() {
        return `${this.state.firstname} ${this.state.lastname}`;
    }

    render() {
        let submitHandler = event => { return this.onSubmit(event); };
        let changeHandler = event => { return this.onChange(event); };

        return (
          <section id="welcome">
            <h2>Welcome</h2>

            <form role="form" onSubmit={submitHandler}>
              <div className="form-group">
                <label htmlFor="firstname">First Name</label>
                <input className="form-control" onChange={changeHandler} placeholder="First Name" type="text" value={this.state.firstname} ref="fn"/>
              </div>
              <div className="form-group">
                <label htmlFor="lastname">Last Name</label>
                <input className="form-control" onChange={changeHandler} placeholder="Last Name" type="text" value={this.state.lastname} ref="ln"/>
              </div>
              <div className="form-group">
                <label>Full Name</label>
                <p className="help-block">{this.fullname}</p>
              </div>
              <button type="submit" className="btn btn-default">Submit</button>
            </form>
          </section>
      );
    }
}

export default Welcome;

Let’s go through this slowly. The constructor sets up our initial state. I’m setting a firstname and a lastname. Next, I define an event handler that will get called when I click on Submit and an event handler when I change the text in one of the text boxes. I’ll come back to the change handler later. I’ve got a computed property next – this is used in both the submit handler to alert “Hello My Name” and within the page render.

Talking of the page render, that’s actually not too complex. Just take it slow and you will see that the JSX is practically identical to the HTML code used in the Aurelia tutorial. However, there is an interesting aspect to those input boxes. The ref attribute is not normal HTML. It’s used by React to find a specific node within this component. It’s similar to the this.$.id in Polymer, but it doesn’t use the id (which can be different). When I get to the change handler, I can use React.findDOMNode to find an element by ref.

On running this project, note the following:

  • Altering either text box will alter the computed field for Full Name
  • Pressing Submit will pop up an alert with the full name

This is a pretty basic in-component interactivity example. You can find the code on my GitHub Repository. I’ve also added a NavToolbar component to finish off the NavBar – it’s a static component for right now, just like NavBrand, so it should be familiar territory.

Wrap Up

There are obvious parallels to draw here between React and Polymer. Both are component technologies and both can render complete pages using sub-components. Both have a level of interactivity that can be built in via private event handling. Both can encapsulate the DOM elements within the component so that they can be referenced easily. Both have a full set of lifecycle functions that can be utilized to easily handle DOM behavior.

React doesn’t require any special features from the browser – it works in any modern browser. Polymer has to polyfill for missing browser features – Shadow DOM, Custom Elements, Templates, and so on. React works fine with ES6 out of the box. Polymer isn’t really ready for ES6 yet. In my tests, React was significantly faster on large DOM changes. And that is the defining thing here. React is fast. For my simple tutorial, that’s not really important. However, transition to a larger project and you really notice the slow down in the DOM when you have to re-draw complete pages.

In the end, it’s a matter of personal preference. Both are young technologies. I suspect that if you are using an MVC architecture and you want components, you will gravitate towards Polymer since they can be easily included. If you want to use a Flux architecture, then you will use React components.

In the next post, I’ll cover a “Flux” architecture and finish off the Aurelia tutorial pages with a full Flux implementation.

ASP.NET, ES2015, React, SystemJS and JSPM

I’ve started investigating a relative newcomer to the JavaScript library, but one that is making a lot of noise. That library is React. But when I combined this with ASP.NET, I found the build processes confusing. There just isn’t a good recipe out there that allows you to write React/JSX components in ECMAScript 6 and get anything like the debugging you want. You lose the source map and any association with the actual source – not too good for the debugging environment. So how do you handle this?

Let’s rewind a bit.

What is React again? It’s a component technology. It occupies the same space as Polymer in that respect, although with vastly differing implementation details. It handles web-based components. It’s got various advantages and disadvantages over other component technologies, but it does the same thing at the end of the day.

I’m not going to go over yet another React tutorial. Really, there are plenty of them even if you don’t know much web dev, including tutorials on React and ES6.

Why am I learning them? Isn’t Polymer enough? Well, no. Firstly, React and Flux are a framework combination that I wanted to learn. I want to learn it mostly because it isn’t MVC and I wanted to see what a non-MVC framework looked like. Flux is the framework piece and React provides the views. Then there are things like React Native – a method of making mobile applications (only iOS at the moment) out of React elements. It turns out to be extremely useful.

As a module system, I like to use jspm. It’s optimized for ES6. So that was my first stop. Can I use jspm + ES6 + JSX + React all in the same application. Let’s make a basic Hello World React app using an ASP.NET based server in Visual Studio.

Step 1: Set up the Server

There really isn’t anything complicated about the server this time. I’m just adding Microsoft.AspNet.StaticFiles to the project.json:

{
  "webroot": "wwwroot",
  "version": "1.0.0-beta5",

  "dependencies": {
    "Microsoft.AspNet.Server.IIS": "1.0.0-beta5",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-beta5",
    "Microsoft.AspNet.StaticFiles": "1.0.0-beta5"
  },

This isn’t the whole file, but I only changed one line. The Startup.cs file is similarly easy:

using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;

namespace WebApplication1
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseStaticFiles();
        }
    }
}

This gets us a web server that serves up the stuff inside wwwroot.

Step 2: Install Libraries

Next is jspm. Run jspm init like I have shown before. Then run:

jspm install react npm:react-dom jsx

This will install the ReactJS library and the JSX transformer for us. I’m using v0.14.0-beta1 of the ReactJS library. They’ve just made a change where some of the rendering code is separated out into a react-dom library. That library hasn’t made it into the JSPM registry yet, so I have to specify where it is.

Step 3: Write Code

First off, here is my wwwroot/index.html file:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Hello World with React</title>
</head>
<body>
    <div id="root"></div>

    <script src="jspm_packages/system.js"></script>
    <script src="config.js"></script>
    <script>System.import("app.js!jsx");</script>
</body>
</html>

Note the !jsx at the end of the System.import statement. That tells SystemJS to run the file through the JSX transformer first. Now, let’s write wwwroot/app.js:

import React from "react";
import ReactDOM from "react-dom";

class HelloWorld extends React.Component {
    render() {
        return (<h1>Hello World</h1>);
    }
}

ReactDOM.render(<HelloWorld/>, document.getElementById("root"));

Don’t try this on any version of React prior to v0.14.0-beta1. As I mentioned, there are two libraries now – react for creating react components and react-dom for rendering them. You need both.

Step 4: Debug Code

This is a debuggers dream. I can see the code and the DOM side-by-side in the browser:

blog-08132015-1

Yep – that’s the original code. The JSX code has been transformed into JavaScript, but the ES6 code is right there. That means I can alter it “in-situ”, set break points, and generally work with it. If an exception occurs, it points at the original source code.

I wouldn’t want to ship this code. When you look at it, this small HelloWorld project loads 2.8MB and over 230 requests with a delay of 4.4 seconds (on localhost!) – just to get one React component rendered. I’d definitely be using Webpack or Browserify on a production site. But this is great for debugging.

Step 5: Code Control – Separate Components

Let’s say I wanted to give HelloWorld its own file. Code organization is important. It’s realatively simple with SystemJS. Just place the following code in wwwroot/components/HelloWorld.js:

import React from "react";

export default class HelloWorld extends React.Component {
    render() {
        return (<h1>Hello World</h1>);
    }
}

This is a copy of the original code, made into an ES6 module. Now I can alter the app.js file accordingly:

import React from "react";
import ReactDOM from "react-dom";

import HelloWorld from "./components/HelloWorld.js!jsx";

ReactDOM.render(<HelloWorld/>, document.getElementById("root"));

Final Notes

The Visual Studio editor is not doing me any favors here. I get errors all over the place. However, I can use this same technique in Visual Studio Code (which handles this syntax better), Atom and other places. This, however, is a great step towards debugging React code in a browser.

Node, MVC Controllers and ECMAScript 2015

Long time readers of my blog will remember that I previously covered Node and MVC applications in a short tutorial series. At that point, I wrote the controllers and loader in ECMAScript 5.1. The code to load the controllers was this:

  fs.readdirSync("./controllers").forEach(function (file) {
    if (file.substr(-3) === ".js") {
      console.info("Loading Controller " + file);
      var base = "/" + path.basename(file, ".js");
      var route = require("./controllers/" + file);
      app.use(base, route);
    }
  });

The typical controller looked like this:

"use strict";

var express = require("express"),
    path = require("path"),
    config = require("../config.json"),
    extend = require("extend");

var router = express.Router(), // eslint-disable-line new-cap
    controller = path.basename(__filename, ".js"),
    loginRoute = config.loginRoute || "/account/login";

/**
 * Set of default properties for the rendering engine
 */
function defaultProperties(req) {
  return {
    title: "Unknown",   // Default title in case the developer doesn't set one
    user: req.user
  };
}

/**
 * Render an appropriate view
 */
function view(req, res, viewName, locals) {
  res.render(controller + "/" + viewName + ".html",
    extend({}, defaultProperties(req), locals));
}

/**
 * GET /{controller=Home}/index
 */
function index(req, res) {
  if (!req.isAuthenticated()) {
    res.redirect(loginRoute);
    return;
  }
  view(req, res, "index", { title: "Home" });
}

// Per-route functionality
router.get("/index", index);

// Default route is to GET index
router.get("/", index);

module.exports = router;

That’s a lot of boilerplate code and it’s completely unreadable for mere mortals. I am working on learning ECMAScript 2015 in depth and I thought I would re-visit this topic. Could I make my controller modules into classes and simplify the whole controller configuration?

Step 1: The New Controller Loader

Since my controllers are going to be classes, I knew I was going to need to adjust the loader. My aim here is just to load the controller classes; not to get the perfect class loader. Here is my code:

// MVC Controllers
var controllerList = {};
fs.readdirSync(path.join(__dirname, "controllers")).forEach(function (file) {
	if (file.substr(-3) === ".js") {
		var basePath = path.basename(file, ".js");
		var Controller = require(`./controllers/${file}`);
		controllerList[basePath] = new Controller(basePath);
		app.use(`/${basePath}`, controllerList[basePath].router);
	}
});

This code loops through every single JavaScript file in the controllers directory. For each one, it constructs a basePath. If the controller is called home.js, then the basePath becomes “home”. I then load the javascript file using a standard “require” statement. Since it’s a class, I create a new object passing in the basePath. I expect that object to expose a router parameter and I use that to link in the router to the basePath. I construct the path using an ES6 template string.

Step 2: The Controller – First Pass

One of the concepts I am pretty religious about is this: Don’t over-complicate the solution early. Get it working, then see if you can do something to make the solution simpler, easy to test, read better, more efficient or whatever you want to do. Here is my first controller:

var express = require("express"),
	extend = require("extend");

export default class HomeController {
	constructor(basePath) {
		this.basePath = basePath;
		this.router = express.Router(); //eslint-disable-line new-cap

		// Route definitions for this controller
		this.router.get("/", (req, res) => { this.index(req, res); });
		this.router.get("/index", (req, res) => { this.index(req, res); });
	}

	renderView(response, viewName, localData = {}) {
		let viewPath = this.basePath + "/" + viewName;
		let defaultData = {
			title: "~~~Unknown~~~"
		};
		let data = extend(defaultData, localData);
		response.render(viewPath, data);
	}

	// GET /home/index (or just /home)
	index(request, response) {
		this.renderView(response, "index");
	}
}

One of the things you will note is that this actually has a lot in common with the ECMAScript5 version of the same controller – it’s just in class form. My module exports the controller class by default. That means I can import it with whatever name I want. The constructor stores the base path that it is passed and creates a new router. The constructor also constructs the routes available in the controller. It uses ES6 fat arrows to preserve the “this” variable.

The renderView method combines a dataset with a view and renders a view. Note I’m using ES6 default parameters and the block-level “let” statement – more ES6 features in use.

Finally, I have a method that actually handles a route. Really, the only unique things for this controller are the index() method that handles a route and the route definition in the constructor.

Step 3: Simplify the Code

This controller class actually works, but I can see a bunch of duplicated code. In the constructor, the basePath and router will always be done this way. I’m allowing the underlying system access to the router variable – definitely not what I want. I want the router to be read-only after creation. Also, the renderView() method is going to be boiler plate code – I want to abstract that away. My simplifying thought here is this: let’s create a Controller class with all the common code in it. We can then extend the Controller class to create the HomeController and only include the “differences”. Here is my new Controller.js file:

var express = require("express"),
	extend = require("extend");

export class Controller {
	constructor(basePath) {
		this.prvBase = basePath;
		this.prvRouter = express.Router(); //eslint-disable-line new-cap
	}

	renderView(response, viewName, localData = {}) {
		let viewPath = this.prvBase + "/" + viewName;
		let defaultData = {
			title: "~~~Unknown~~~"
		};
		let data = extend(defaultData, localData);
		response.render(viewPath, data);
	}

	get basePath() {
		return this.prvBase;
	}

	get router() {
		return this.prvRouter;
	}
}

A lot of this code comes from the original home.js code. I’ve converted the basePath and router variables into ES6 getters so that I can make them read-only (assuming one uses the published API). Now, what does an implementation of a controller look like? Let’s look at the new home.js:

import {Controller} from "../mvc/Controller";

export default class HomeController extends Controller {
	constructor(basePath) {
		super(basePath);

		// Route definitions for this controller
		this.router.get("/", (req, res) => { this.index(req, res); });
		this.router.get("/index", (req, res) => { this.index(req, res); });
	}

	index(request, response) {
		this.renderView(response, "index");
	}
}

This is getting much closer to where I want to be. The super() call is for running the constructor of the class I am extending, thus setting up the common code. I still have to define the routes within the constructor, but I don’t have any boiler-plate code.

What else would make this controller object awesome? ECMAScript 7 is defining a concept called decorators. With ES7 decorators, I could theoretically do something like this:

export default class HomeController extends Controller {
    @HttpGet([ "/", "/index" ])
    index(request, response) {
        this.renderView(response, "index");
    }
}

Of course, ES2015 (also known as ES6) is just out and I don’t expect ES7 to be ratified for a number of years, so there is no guarantee that anyone will support ES7 decorators. You can check out the compatibility chart at Kangax. Note that only Babel supports ES7 decorators right now.

I’m going to delve into decorators in another blog post. For now, this mechanism is great for developing an MVC application without the need of libraries beyond the standard ExpressJS.

Visual Studio Code and Trimming Whitespace

Have you noticed that eslint doesn’t like trailing whitespace. It has a rule for it: the no-trailing-spaces rule.

Normally, this wouldn’t be a problem. I’m normally using Visual Studio 2015. Visual Studio takes care of it. Firstly, when you are typing JavaScript, the editor properly indents and doesn’t give you blank lines with spaces on it. Secondly, I have a plug-in called the Trailing Spaces Visualizer – it’s an extension that highlights trailing spaces.

This is all well and good, but I’m using Visual Studio Code now since it actually supports ECMAScript 2015. When you hit enter twice (to create a blank line), the blank line has spaces up to the indent level of the prior line and eslint complains of trailing spaces.

Fortunately, there are a good couple of options here. Option 1 is to trim the lines. Press Ctrl + Shift + X in the editor and the current buffer will be trimmed. You can rebind this to something else by editing your keybindings.json to something like this:

[{ 
  "key": "shift+f12",
  "command": "editor.action.trimTrailingWhitespace",
  "when": "editorTextFocus"
}]

You can open up your personal keybindings.json using File -> Preferences -> Keyboard Shortcuts.

Option 2 is to automatically trim the white space on save. Do this by editing your user preferences (under File -> Preferences -> User Settings). Add the following to the file:

{
  "files.trimTrailingWhitespace": true
}

Your final option is to disable the rule in question. You can do this on a per-file basis or via the .eslintrc file in your top level directory, like this:

{
  "env": {
    "node": true,
    "es6": true
  },
  "ecmaFeatures": {
    "modules": true
  },
  "rules": {
    "no-trailing-spaces": 0,
    "global-strict": 0,
    "strict": [ 2, "global" ]
  }
}

If you are coding in ECMAScript 2015, don’t forget to also configure VS Code to recognize the new language constructs. You can do this by creating a jsconfig.json file in your project root. It should have the following contents:

{
	"compilerOptions": {
		"target": "ES6",
		"module": "commonjs"
	}
}

Once you have created the file and saved it, restart VS Code and the new language constructs will be recognized.

ASP.NET MVC6 Identity Part 4 – AJAX Authentication

In the last few articles, I’ve covered the following:

  1. Creating an ASP.NET Identity Database
  2. Data Annotations and Custom Validators for Models
  3. A WebAPI Authenticator
  4. An ECMAScript 6 Modal Dialog

Four articles and I still haven’t logged in to my application. Today that is going to change because I’m writing the front-end AJAX code to do the authentication handling.

Doing AJAX Request Promises

Some months ago, I wrote about doing ECMAScript 6 HTTP Requests with Promises. I have a library for that now and I’m going to use it in this project. It’s stored in Static/js/ajax.js. Let’s walk through it:

/**
 * Routines for dealing with AJAX
 */
/*eslint no-console:0 */
"use strict";

function callAjax(method, url, query, body, headers) {
    console.debug("[callAjax] method=%s url=%s query=%o body=%o headers=%o", method, url, query, body, headers);

One method is all it takes to handle all the AJAX functionality. Note that I’m using an eslint directive at the top to say “I’m going to use console statements, so be quiet about it”. When I change over to a non-debug version, I’ll remove that line and all the console statements.

    let uri = url;
    if (query != null) {
        console.debug("[callAjax] query has been specified - processing");
        if (typeof query === "object") {
            console.debug("[callAjax] query is an object");
            let qs = Object.keys(query).map(k =&gt; encodeURIComponent(k) + "=" + encodeURIComponent(query[k]));
            uri = uri + "?" + qs.join("&amp;");
        }
        else if (typeof query === "string") {
            // Assume the query string is already encoded
            console.debug("[callAjax] query is a string (adding unmodified)");
            uri = uri + "?" + query;
        }
        console.debug("[callAjax] New URI is %s", uri);
    }

The next block turns an object, say {"Email":"foo","Password":"bar"} into the appropriate URI encoded query string Email=foo&Password=bar. If the function got passed a string instead of an object, it just uses the string that is provided. It constructs the new URI based on this query string.

    let requestBody = "";
    if (body != null) {
        console.debug("[callAjax] Body has been specified - processing");
        if (typeof body === "object") {
            console.debug("[callAjax] body is an object");
            requestBody = JSON.stringify(body);
            headers["Content-type"] = "application/json";
        } else if (typeof body === "string") {
            console.debug("[callAjax] body is a string (adding unmodified)");
            requestBody = body;
        }
        console.debug("[callAjax] BODY = %s", requestBody);
    }

Next up is the body – used in POST and PUT REST calls. I’m using the JSON methods that are built into pretty much every browser these days. If the method is passed an object, I turn it into JSON and then update the headers to include a Content-type header. As with the query parameters, if I pass a string then I just include it and assume the caller knows what they are doing.

    return new Promise(function (resolve, reject) {
        console.debug("[callAjax] Creating new XMLHttpRequest");
        let request = new XMLHttpRequest();
        console.debug("[callAjax] Open a %s request to %s", method, uri);
        request.open(method, uri);
        for (var p in headers) {
            if (headers.hasOwnProperty(p)) {
                console.debug("[callAjax] Add header %s: %s", p, headers[p]);
                request.setRequestHeader(p, headers[p]);
            }
        }

        console.debug("[callAjax] Set resolve to the onload object");
        request.onload = function() {
            resolve(request);
        };

        console.debug("[callAjax] Set reject to the onerror object");
        request.onerror = function() {
            reject(request);
        };

        console.debug("[callAjax] Send requested body");
        request.send(requestBody);
    });
}

Finally, I construct the XMLHttpRequest wrapped in a promise. Since I expect that different codes are going to get returned, I’m not going to assume that 200 is the only valid code. I did this in the prior version of the library. Instead I say “success is when the server responds and failure is when the server does not response”.

/**
 * Helper Functions for each method
 */
function ajaxDelete(url, query, headers) { //eslint-disable-line no-unused-vars
    return callAjax("DELETE", url, query || {}, null, headers || {});
}

function ajaxGet(url, query, headers) { //eslint-disable-line no-unused-vars
    return callAjax("GET", url, query || {}, null, headers || {});
}

function ajaxPost(url, args, headers) { //eslint-disable-line no-unused-vars
    return callAjax("POST", url, null, args, headers || {});
}

function ajaxPut(url, args, headers) { //eslint-disable-line no-unused-vars
    return callAjax("PUT", url, null, args, headers || {});
}

export { ajaxDelete, ajaxGet, ajaxPost, ajaxPut };

Finally, I set up a number of functions that send the right arguments to the callAjax() method. GET and DELETE calls use a query method. POST and PUT calls use a body method. This way every method uses the same arguments and the right format gets sent to the backend.

Feel free to co-opt this library file for yourself.

Calling the WebAPI

Now, how do we use this library? In the last article I created a LoginModal class for handling the login modal. Let’s take a look at the new code:

/**
 * Handler for the Login Modal
 */
/*eslint no-console:0 */
"use strict";

import { ajaxPost } from "./ajax";

class LoginModal {
    /**
     * Constructor - store the ID that activates us and then
     * wire up the activator.
     */
    constructor(activatorEl, modalEl) {
        // Store all the elements for later
        this.activator = activatorEl;
        this.modal = modalEl;
        this.modalClose = modalEl.querySelector(".modalClose");
        this.submitButton = modalEl.querySelector("button#loginButton");

        // Make the activator cursor a pointer to show it is clickable
        this.activator.style.cursor = "pointer";

        // Wire up the click event handlers for the activator and modal close
        this.activator.addEventListener("click", (e) =&gt; { return this.activate(e); });
        this.modalClose.addEventListener("click", (e) =&gt; { return this.close(e); });

        // Wire up the submission button for the form
        this.submitButton.addEventListener("click", (e) =&gt; { return this.submit(e); });

        // Ensure the modal is hidden
        this.modal.style.display = "none";
        this.modal.style.opacity = "0";

        return;
    }

As with the AJAX library, I’m using the eslint directive to disable complaints about the console. I then bring in the ajaxPost method (the only one I need in this file) from the AJAX library above.

In the constructor, I’ve added information about the submit button and wired up an event handler for when the user clicks on the submit button.

   /**
     * Someone hit the submit button.
     */
    submit(e) {
        let modal = this.modal,
            submitButton = this.submitButton,
            spinner = "<i class='fa fa-spinner fa-pulse'></i> ",
            submitContent = this.submitButton.innerHTML;

        // Deactivate the form
        submitButton.disabled = true;
        submitButton.innerHTML = spinner + submitContent;

The first thing we do when going into the submit button event handler is to deactivate the form. Sometimes you will have a slow link – you don’t want someone clicking repeatedly on the submit button and having that kick off tons of requests to the backend – the idea is to reduce the load on the backend, not increase it. To indicate that the form is busy, I’ve added a spinner to the button content.

        // Validation goes here (eventually)

        // Submit AJAX Request
        let requestArgs = {
            "Email": this.modal.querySelector("input[name=Email]").value,
            "Password": this.modal.querySelector("input[name=Password]").value
        };
        console.debug("[LoginModal#submit] requestArgs = %o", requestArgs);

I’m not doing client side validation (yet). I’ll get to it. From the WebAPI work, I know that my request has to be a JSON request with the Email and Password fields, so I need to construct an object that I can pass along. Next step is the actual AJAX call:

        ajaxPost("/api/login", requestArgs)
            .catch(function(error) {
                console.error("[LoginModal#submit] Error in AJAX Call to /api/login: %o", error);
            })
            .then(function (response) {
                console.debug("[LoginModal#submit] AJAX Call to /api/login: Response = %o", response);
                if (response.status === 200) {
                    // We got a 200 Success back, so refresh the page
                    location.reload();
                } else if (response.status === 400) {
                    let r = JSON.parse(response.response);

                    // If there were errors, then add them to the appropriate areas on
                    // the form.  If there weren't errors, make sure those same areas
                    // don't have errors (handles multiple submissions)
                    if (r[""]) {
                        modal.querySelector("#errorForSignInModal").innerHTML = r[""][0];
                    } else {
                        modal.querySelector("#errorForSignInModal").innerHTML = "";
                    }
                    if (r.Email) {
                        modal.querySelector("#errorForEmail").innerHTML = r.Email[0];
                    } else {
                        modal.querySelector("#errorForEmail").innerHTML = "";
                    }
                    if (r.Password) {
                        modal.querySelector("#errorForPassword").innerHTML = r.Password[0];
                    } else {
                        modal.querySelector("#errorForPassword").innerHTML = "";
                    }

                    // Re-activate the form
                    submitButton.innerHTML = submitContent;
                    submitButton.disabled = false;
                }
            });

        e.stopPropagation();
        return false;
    }

If you remember from my discussion on ES6 Promises, I can catch errors and handle responses asynchronously. The catch statement says “there is an error” – right now, I’m just logging the error in the console and not re-activating the form. This isn’t very friendly and I should probably do something about that.

In the then clause, I handle the response. There are two possible responses from the WebAPI – a 200 Success with a few cookies or a 400 Bad Request with some JSON. If the response is Success then the browser already knows about the cookies and all I have to do is reload the page.

If the response is a 400 Bad Request, then I turn the JSON response into an object and look for things I’m interested in, placing the response in prepared locations in the modal dialog. Once that is done, I restore the button content (which removes the spinner) and re-enable the submit button.

Running the Code

If you run this code and click on the Sign In button, the modal will pop up. At this point you can bring up the F12 Developer Tools and hop over to the Console window. Enter some information and see what comes up:

blog-code-0606-1

I’ve added a number of console.debug statements so you can see what is happening. You can also click on any of the objects with a triangle beside them to see the actual contents. Here I’ve entered “admin@” as the username, so I’m expecting a 400 Bad Request, which is exactly what I get.

Problems Still to be Solved

There are two problems to be solved. Firstly, users like to be able to press Enter in the text boxes to submit the form. I’m not capturing key presses within the form so I can’t emulate that functionality. Right now, the only submission possibility is clicking on the button.

Secondly, if there is an error in transmission then there is no indication. The form will continue to spin. This is an easy fix and I’ll do it before I check in the code.

Finally, I don’t do any client-side validation. I leave the validation to the server-side. This means that there are extra round-trips happening when it’s not really necessary. I’ll fix that in the next article.