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.

19 Jun 2015, 00:00

Elegant way to use React with ES6/ES7 features.

React, JSX, ES6.

So you want React, JSX the markup and write ES6/7 code style, but setting a working environment may be pain in the ass,

More to say, Facebook announced that its JSTransformer and react-tools going to be deprecated,

It seems like it’s starting to get confusing how to set a full working environment with JSX transformation and ES6/ES7 support.

While React 0.13.0-beta-1 announced great support for ES6, it still unclear how to build a full working environment that supports ES6 either,

You can find multiple boilerplate projects at github using WebPack, Browserify and other module loader tools available nowadays but I found all of them unclean, full of build scripts and things that just make things more complicated,

After doing some research, I feel like the best approach would be to go with JSPM repository that is based on SystemJs dynamic module loader.

The chosen tools:

  1. SytemJs - It is a Universal dynamic module loader, it supports AMD, CommonJS but the best of it is its native support for ES6 modules, with native support for Babel as its transpiler to ES5, it also uses JSPM which supports NPM and Github repos such as Bower does, so you can enjoy packages from both worlds.
  2. Babel as the ES6 transpiler, this transpiler is responsible to translate ES6 coding to ES5 as ES6 is not supported yet by most browsers, Babel is also supported by Facebook and provides JSX native transformation.

Enough said, here’s some code, we’ll start with empty folder!

Setting a clean working environment

Pre requisites

Lets install pre requisites:

npm install -g jspm
npm install -g http-server

Initializing Project

Create an empty folder and run

jspm init

You can choose default answers for all questions if not sure,

This will create a package.json and a config.js file required for SystemJs to work properly.

Now lets tweak config.js a bit to support ES7 so you can enjoy ES7+ property initializers and other ES7 cool features

"babelOptions": {
  blacklist: [],
  stage: 0,
  "optional": [
    "runtime"
  ]
},

blacklist: [] tells Babel not to ignore JSX transformation as by default it’s disabled, stage: 0 tells Babel that we want to use experimental ES7 syntax.

Creating an index.html file

Lets create our index file as every web app that respect itself has one!

Simply create index.html in the root folder with your favorite editor

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Title Here</title>
    </head>
    <body>
        <!-- build:js -->
        <script src="jspm_packages/system.js"></script>
        <script src="config.js"></script>
        <script>
            System.import('app/main');
        </script>
        <!-- endbuild -->
    </body>
</html>

See how clean and elegant is it? we just load system.js as our dynamic module loader and the generated config.js that holds our SystemJs configuration.

Then we import app/main as our first ES6 module that serves the application.

Create a simple React based class.

Thanks to SystemJs, we can now fully write application modules, lets create our main application entry point

Create a file app/main.js with the following content:

import React from 'react';
import App from './app';

React.render(<App/>, document.body);

This just import React and renders our App component.

Her eis the app/app.js file content:

import React from 'react';
var {Component} = React;

export default class MyApp extends Component {
    static propTypes = {
       flux: React.PropTypes.object.isRequired
   }

    render () {
        return (
            <div>Hello</div>
        )
    }
}

Now run http-server in your folder,

hitting http://localhost:8080 should display Hello :)

Summary

The combination of React, JSX transformation via Babel, and ES6/7 support via SystemJS provides a great clean and elegant way to write React code without the overhead of build systems and ugly scripts around.

01 May 2015, 00:00

Facebook React - simplified work flow.

React is a really game changer in the world of web development, As most web frameworks (such Angular, Ember, etc) supports two way bindings that really simplifies development life, when applications start to get bigger things start to get clashed as multiple views may be bound to multiple models and getting unexpected behaviors is not something imaginary,

React solve these problems by exposing a new flow that is based on unidirectional binding, combined with the usage of virtual DOM, DOM reconciliation should result a better performance than two way bindings based frameworks, Well, if Facebook uses it, then it scales :)

You can read about it in React’s web site, especially the Tutorial should give you a great starting point,

Watch out my next post about how to setup a React environment using great tools that will simplify your development lifecycle.