React and ES6 - Part 1, Introduction
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:
- React and ES6 - Part 1, Introduction into ES6 and React
- React and ES6 - Part 2, React Classes and ES7 Property Initializers
- React and ES6 - Part 3, Binding to methods of React class (ES7 included)
- React and ES6 - Part 4, React Mixins when using ES6 and React
- React and ES6 - Part 5, React and ES6 Workflow with JSPM
- React and ES6 - Part 6, React and ES6 Workflow with Webpack
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.
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:
After running babel for that code you will have:
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.
- Obviously, you will need node.js. Install it on your system if you don’t have it.
- Next, you will need to install Gulp globally:
npm install --g gulp
. - Switch to your project’s directory. Initialize your
package.json
file by usingnpm init
and answering appeared questions. - Run
npm install --save react react-dom
. This will installreact
npm module into yournode_modules
folder and save React library as dependency inside your package.json file. - Run
npm install --save-dev gulp browserify babelify vinyl-source-stream babel-preset-es2015 babel-preset-react
. This will install more development dependencies to yournode_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 typinggulp build
. - Line 7. We start to describe what our
build
task will do. We tell Gulp to use Browserify forapp.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 typinggulp watch
. This task will runbuild
task whenever any ofjsx
file changes. - Line 18. We define default gulp task that could be run by typing
gulp
. This task simply executeswatch
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 simplerender
method which returns<h1>
tag containingphrase
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.