ES7, Harmony and Future JS

Before development let's jump start into some upcoming features of JS which increase expressiveness.

An important part of good code is readability. It's important to have concise code with good comments so you can understand it immediately... especially when you come back to code after a few months.

Making UI code readable: future JavaScript

ES7 — also known as strawman proposals — combine ES6 with more features that improve the expressiveness of JS. Write your source as ES6/7 and use the Babel transpiler to convert your code to JS that browsers currently support.

Learning ES6/7

ES6/7 isn't a new language... the features are easy enough to learn. Babel, the transpiler, has a great resource for jumping into ES6: https://babeljs.io/docs/learn-es2015/. They also have an online REPL — you can paste in ES6/7 to see transpiled ES5 immediately. It's great for understanding how the transformation works.

A few common ES6 features within UI code

Destructuring

Destructuring allows us to yank values from an array or object, which grants a readability bonus. Here's how it works:

let [a, b] = [1, 2];
// a === 1
// b === 2

let { ui, name } = this.props;
// ui === this.props.ui;
// name === this.props.name

let { blogpost: { title, slug } } = this.props;
// title === this.props.blogpost.title;
// slug === this.props.blogpost.slug;
Function Binding (::)

Function binding (simply ::) is a time-saver and readability bonus for binding scope to a callback within your components.

class Link extends Component {

  click() {
    console.log(this.props);
    console.log('Clicked with scope', this);
  }

  render() {
    return <a href='#' onClick={ ::this.click }>Click me!</a>
  }

}

Adding the function bind syntax to ::this.click converts down to this.click.bind(this), ensuring that your callbacks in a component are called with this scoped to the component.

The documentation and proposal can be read at https://github.com/zenparsing/es-function-bind.

Spread operator (...)

The spread operator allows us to expand an object or array without iteration:

import * as postActions from 'actions/posts';
import * as userActions from 'actions/users';

let actions = (dispatch) => {
  return bindActionCreators({ ...postActions, ...userActions}, dispatch);
}

In this example we create a new object containing all values from postActions and userActions in one line.