This is the first post of series in which we are going to explore the usage of React with ECMAScript6.

You could find links to all parts of series below:

The code corresponding to this article is available on the GitHub.

Update from 03.11.2015: Updated the code and text to use Babel 6 instead of Babel 5.

Update from 20.05.2016: Updated the code and text to use React 15.

React Logo JavaScript Logo

Since announce of ReactJS v0.13.0 Beta 1 it’s possible to use capabilities of ECMAScript 6 for your React components. What advantages it brings to us as developers?

Well, ECMAScript6 (or ECMAScript 2015) is new standard (that will hopefully be finalized in 2015, update from 26.06.2015 - it is now officially standard - link!) that brings whole bunch of new features into the world of JavaScript. Such a features include classes, arrow functions, rest parameters, iterators, generators … and a lot, lot more.

If you are not familiar with new features of ECMAScript 2015, I would highly recommend you to go through them using this link.

By looking at ES6 compatibility table we could notice that not all the browsers support every single feature of ES2015. Luckily, you don’t have to spend ages until vendors will ship ECMAScript 6 features to the browsers. There are already existing solutions called transpilers that convert your code written in ES6 to ES5-compatible code. That’s very similar to how CoffeeScript turns your Coffee code into JavaScript.

One of these solutions is Babel, really amazing tool. Many thanks to its authors. What’s good, Babel supports a huge amount of different frameworks, build systems, test frameworks, template engines - look here.

To give you a quick idea of how babel works here is an example. Say, we have following code written in ECMAScript 6:

var evenNumbers = numbers.filter((num) => num % 2 === 0);

After running babel for that code you will have:

var evenNumbers = numbers.filter(function (num) {
  return num % 2 === 0;
});

A similar concept applies to other ES6 language constructs.

Preparing development environment

In order to have a continuous workflow with babel, we will use Gulp. This is task runner built on top of node.js which could improve your life by automating tedious tasks. If you heard about Grunt then Gulp has the same purpose.

  1. Obviously, you will need node.js. Install it on your system if you don’t have it.
  2. Next, you will need to install Gulp globally: npm install --g gulp.
  3. Switch to your project’s directory. Initialize your package.json file by using npm init and answering appeared questions.
  4. Run npm install --save react react-dom. This will install react npm module into your node_modules folder and save React library as dependency inside your package.json file.
  5. Run npm install --save-dev gulp browserify babelify vinyl-source-stream babel-preset-es2015 babel-preset-react. This will install more development dependencies to your node_modules.

To learn more about different modules installed at step 5, please refer to my article about Browserify, Babelify and ES6.

Creating gulpfile.js

Create file named gulpfile.js in the root directory of your project with following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');

gulp.task('build', function () {
    return browserify({entries: './app.jsx', extensions: ['.jsx'], debug: true})
        .transform('babelify', {presets: ['es2015', 'react']})
        .bundle()
        .pipe(source('bundle.js'))
        .pipe(gulp.dest('dist'));
});

gulp.task('watch', ['build'], function () {
    gulp.watch('*.jsx', ['build']);
});

gulp.task('default', ['watch']);

I guess, some explanations would be helpful.

  • Lines 1-4. We require installed node.js modules and assign them to variables.
  • Line 6. We define gulp task named build that could be run by typing gulp build.
  • Line 7. We start to describe what our build task will do. We tell Gulp to use Browserify for app.jsx. Additionally, we turn on debug mode which is beneficial for development.
  • Lines 8-11. We apply Babelify transform to our code. This allows us to convert code written in ECMAScript6 to ECMAScript5. Next we output the result to dist/bundle.js file. Update from 03.11.2015: These lines now use new feature of Babel 6 called presets.
  • Lines 14-16. We define gulp task named watch that could be run by typing gulp watch. This task will run build task whenever any of jsx file changes.
  • Line 18. We define default gulp task that could be run by typing gulp. This task simply executes watch task.

Your typical workflow will include typing gulp in a terminal and pressing Enter key. It will watch for changes inside your React components and re-build everything continuously.

JSX and Babel

You might already notice that we are using .jsx extension instead of .js. JSX is special JavaScript syntax extension developed by ReactJS team. This format is delivered especially for the more convenient development of ReactJS components.

Here is more information about JSX.

Another useful thing - Babelify understands JSX syntax out of the box (more about this in
blog post).

Writing first React component using ECMAScript 6

Hope you are not too bored by this time :)

It’s time to create our first very simple component using ES6. Add file named hello-world.jsx to root of the project:

1
2
3
4
5
6
7
8
9
import React from 'react';

class HelloWorld extends React.Component {
    render() {
        return <h1>Hello from {this.props.phrase}!</h1>;
    }
}

export default HelloWorld;

Some explanation:

  • Line 1. We import React library and put it to a variable named React.
  • Lines 3-8. Creation of React component using ES6 class by extending React.Component class. We add very simple render method which returns <h1> tag containing phrase prop.
  • Line 9. We export just created a component to outside world using export default HelloWorld.

For simpler understanding, I placed the code for the same component, but written without usage of ES6 classes:

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';

var HelloWorld = React.createClass({
    render: function() {
        return (
            <h1>Hello from {this.props.phrase}!</h1>
        );
    }
});

export default HelloWorld;

Wrapping up

Let’s finish our simple example.

Create file named app.jsx:

1
2
3
4
5
6
7
8
import HelloWorld from './hello-world';
import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
    <HelloWorld phrase="ES6"/>,
    document.querySelector('.root')
);

Here we import HelloWorld component created on the previous step and set phrase prop of that component. Please also note that we use special react-dom package for rendering of the HelloWorld component. That’s because core React package is separated from rendering package starting from React version 0.14.

Next, let’s create index.html:

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>ReactJS and ES6</title>
</head>
<body>
<div class="root"></div>
<script src="dist/bundle.js"></script>
</body>
</html>

Now run gulp from a terminal (it will create dist/bundle.js file) and open this HTML file in your browser.

You should see below image.

Screenshot

Further Reading