14 Sep 2015, 00:00

Default function options stash with ES6 destructuring assignment.

ES6 opens up a clean approach to define function options stash thanks to the destructuring assignment syntax,

Assuming we want options but let the user overrides it, we can declare our function that way:

function hello(param1, {debug = true, whatever = false} = {}) { }

The advantages are, clearly there is no code in the body function to achieve default options & user overrides.

13 Sep 2015, 00:00

Add additional properties to a result of a function or a fucntion map using ES6 spread operator.

Sometimes it makes sense to add additional properties to a result of a function,

Examples could be enhancing an operation result with some meta data, extending with a timestamp, run time, etc,

Using ES6, we could easily achieve this by:

bindData(oper, props) {
  if (typeof oper === 'function') {
    return (...args) => ({
      ...oper(...args),
      ...props
    });
  }
  if (typeof oper === 'object') {
    return Object.keys(oper).reduce((prev, key) => ({
      ...prev,
      [key]: bindData(oper[key], props)
    }), {});
  }
  return oper;
}

Here are some clarifications:

  1. If oper is a function, we decorate the original function by a closure, return (...args) is the closure (read more about the spread operator.

In general, myFunction(...args); is equelevent to (args) { oper.apply(null, args); },

  1. When the returned function is invoked, the result of the original function ...oper(...args) is then merged with the props object, in other words:

...oper(), ...props is equelevent to: Object.assign({}, oper(), props); Read more about Object.assign

  1. If oper is an object, we bind each of its key’s recursively (assuming each property is a function).

05 Sep 2015, 00:00

ES6, React & Browserify

ES6, React & Browserify

Browserify is a lightweight build tool for JS, you can start ‘require’ modules with zero configuration, Thanks to Babelify, you can start writing ES6 code (via Babel) write away,

Here’s a proof how simple it is,

Lets create a package.json file and install minimal dependencies

npm init
npm install --save react
npm install --save-dev browserify babelify watchify

Lets give Browserify a hint that it should perform code transformation via babelify by adding this json tag to package.json

"browserify": {
  "transform": [
    "babelify"
  ]
}

It can also be nice to just type npm start when developing, so lets add a start script to package.json as well

“start”: “watchify –extension=js -o bundle.js index.js & python -m SimpleHTTPServer”,

Note: Watchify is not mandatory but it’s great tool for watching your code changes and auto rebuild when a change gets discovered.

Lets put the simplest index file ever:

<html>
  <body>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>

Here’s a simple ES6 class with React.

import React from 'react';

class Hello extends React.Component {
  constructor(props) {
    super(props)
    this.state = {count: props.initCount}
    this.tick = this.tick.bind(this)
  }

  tick () {
    this.setState({count: this.state.count + 1});
  }
  render(){
    let { name } = this.props
    let { count } = this.state
    return (
      <button onClick={this.tick}>Hello {name} {count}</button>
    );
  }
}

React.render(<Hello name="Stranger" initCount={5}/>, document.body)

Running the code:

npm start

Open browser http://localhost:8000

To summary:

1) Browserify is lightweight build tool, it handles modularity by understanding require 2) Labelify is a plugin for Browserify, it takes care of transpilling ES6 code to ES5 via Babel. 3) Thanks to Babel & React integration, there’s no need for any extra plugins to perform JSX transformations.

23 Jun 2015, 00:00

Extending behavior of React Components by ES6 Decorators & Higher Order Components

About Mixins & Higher Order Components

Sometimes it makes sense to extends a behavior of a component, while mixins are still alive, they’r not recommended anylonger, use Higher Order Components instead.

So instead of doing this:

function StoreMixin(...stores) {
  var Mixin = {
    getInitialState() {
      return this.getStateFromStores(this.props);
    },
    ...
  }
}

var UserProfilePage = React.createClass({
  mixins: [StoreMixin(UserStore)],
  propTypes: {
    userId: PropTypes.number.isRequired
  },
  ...
})

You can do that:

function connectToStores(Component, stores, getStateFromStores) {
  const StoreConnection = React.createClass({
    getInitialState() {
      return getStateFromStores(this.props);
    },
    ...
    render() {
      return <Component {...this.props} {...this.state} />;
    }
  })
}

We just wrap the component and passes some additional props to it, it is a clean and generic solution for extending components without merging behaviors being implemented by React’s mixin merge logic.

You can read more about Higher Order Components here

Extending via ES6 Decorators

Sometimes it makes sense to extends a component without the need to wrap it manually, this technique is common in different frameworks to define components less verbosely when extra functionality is demanded.

Here is a short example how it works, Lets extends the context of our component hierarchy with a print function, so we use it in our render method:

class MyPage extends Component {
    static contextTypes = contextTypes;
    render() {
        return(
            <div>{this.context.print('Hello World')}</div>
        )
    }
}

Assuming MyPage is a child component of App, here is how our App component looks like:

var contextTypes = {
    print: PropTypes.func.isRequired
}

var myContext = {
    print: (m) => (m)
}

@context(contextTypes, myContext)
export default class App extends Component {
    render() {
        return (
            <MyPage/>
        )
    }
}

And here is the code of the decorator:

export default function context(contextTypes, context) {

    return function (DecoratedComponent) {
        return class {
            static childContextTypes = contextTypes;
            getChildContext() {
              return context;
            }
            render() {
              return (
                <DecoratedComponent {...this.props} />
              );
            }
        }
    }
}

The Decorator expects an expression and invokes the function with the given parameters and must return a function that expects the annotated component as a parameter, then we just return a class with some context the wraps our component.

You can read more about Decorators here.