How to get started with React js in ES6

Note: This post is outdated, here is an updated post

In this post I will give you a simple set up or boilerplate for starting a React project in ES6. This boilerplate is not meant to be used for professional stuff. Use it to get started and then you can structure it in a better way.

If you are just looking to get started up with ES6, you can take a look at my previous post.

Set up the project

Let's start off by creating a package.json and downloading the required modules, write the following in your terminal: npm init and set up the project. After that, we need to download react as a dependency: npm install --save react Then do npm install --save-dev gulp babelify reactify browserify vinyl-source-stream gulp-util to download our development dependencies.

Set up Gulp

Gulp is a task runner and will automate the transformation from ES6 to ES5, since browsers don't support ES6 yet. I have written a post on task runners where you can read up on Gulp if you don't know what it is. Basically it will automate several tasks, in this case it will transform both jsx and es6 to javascript and bundle everything together. Read the comments inside the code for more  explanation. Create this file in the root of your project.
/*
*	Task Automation to make my life easier.
*	Author: Jean-Pierre Sierens
*	===========================================================================
*/

// declarations, dependencies
// ----------------------------------------------------------------------------
var gulp = require('gulp');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var gutil = require('gulp-util');
var babelify = require('babelify');

// External dependencies you do not want to rebundle while developing,
// but include in your application deployment
var dependencies = [
	'react',
  	'react/addons'
];
// keep a count of the times a task refires
var scriptsCount = 0;

// Gulp tasks
// ----------------------------------------------------------------------------
gulp.task('scripts', function() {
    bundleApp(false);
});

gulp.task('deploy', function(){
	bundleApp(true);
});

// When running 'gulp' on the terminal this task will fire.
// It will start watching for changes in every .js file.
// If there's a change, the task 'scripts' defined above will fire.
gulp.task('default', function() {
	gulp.watch(['./**/*.js','!./web/*.js'], ['scripts']);
});

// Private Functions
// ----------------------------------------------------------------------------
function bundleApp(isProduction) {
	scriptsCount++;
	// Browserify will bundle all our js files together in to one and will let
	// us use modules in the front end.
	var appBundler = browserify({
    	entries: 'app.js',
    	debug: true
  	})

	// If it's not for production, a separate vendors.js file will be created
	// so that we don't have to rebundle things like react everytime there's a 
	// change in the js file
  	if (!isProduction && scriptsCount === 1){
  		// create vendors.js for dev environment.
  		browserify({
			require: dependencies,
			debug: true
		})
			.bundle()
			.on('error', gutil.log)
			.pipe(source('vendors.js'))
			.pipe(gulp.dest('./web/js/'));
  	}
  	if (!isProduction){
  		// make the dependencies external so they dont get bundled by the 
		// app bundler. Dependencies are already bundled in vendor.js for
		// development environments.
  		dependencies.forEach(function(dep){
  			appBundler.external(dep);
  		})
  	}

  	appBundler
  		// transform ES6 and JSX to ES5 with babelify
	  	.transform(babelify)
	    .bundle()
	    .on('error',gutil.log)
	    .pipe(source('bundle.js'))
	    .pipe(gulp.dest('./web/js/'));
}
For development environments we will use two files: vendors.js and bundle.js. This is because when we are watching the js files, everytime there is a change on a file, gulp will fire a rebundle process. There is no need to rebundle all the dependencies like the react files, so we put those apart in vendors.js. Otherwise you would have to rebundle them everytime there is a change and that takes a little more time. Once you want your project ready for production, gulp deploy will create a single 'bundle.js' files which will contain everything, dependencies + your javascript code.

Your HTML file

Create a file in the root called 'index.html'. Here you will create a simple page structure that will hold the vendors.js and bundle.js scripts (they will be created by gulp later) as well as the container for the react element:
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>React and ES6</title>
</head>
<body>
	<!-- React element goes here -->
	<div id="searchableTable"></div>

	<!-- one script to rule them all (in production) -->
	<script src="js/vendors.js"></script>
	<script src="js/bundle.js"></script>
</body>
</html>

App.js file

Now to the app. Create a file called 'app.js' in the root of your project.
import React from 'react';
import SearchableTable from './components/SearchableTable';
import {data} from './components/data';

// Filterable CheatSheet Component
React.render(<SearchableTable data={data}/>, document.getElementById('searchableTable'));
Simple. All you are doing here is importing react with the ES6 syntax as well as a module called searchableTable and the data we will be using. We will be creating these two modules later. Then you are rendering the component searchableTable inside the div we created earlier in our HTML and passing it the data.

The React Components

Now this tutorial isn't meant to introduce you to react. If you are new to react then I really recommend reading this tutorial or this one. I prefer the second as I think I understood more from it, but read the two and you will definitely understand what react is about. Before showing you the components, it would be good to show you the data this components use. Create a folder in your root called 'components', under it create a file called 'data.js'.
export const data = [
  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];
The data is just an array of product objects. The data and react components here are taken from the second tutorial with a twist, and of course, in ES6 instead of the tutorial's ES5 version. Under the 'components' folder create another file called 'SearchableTable.js'.
/*
*	Searchable Table
*	Author: Jean-Pierre Sierens
*	===========================================================================
*/

import React from 'react';

export default class SearchableTable extends React.Component {
	constructor() {
		super();
		// Initial state of the component
        this.state = {filterText: ''}
    }
    handleUserInput(filterText) {
    	// When there's a change in the state, the component and all its 
    	// sub-components get updated.
        this.setState({filterText: filterText});
    }
	render(){
		return (
			<div>
				<SearchBar 
					filterText={this.state.filterText}
                    onUserInput={this.handleUserInput.bind(this)}
                />
				<Table 
					data={this.props.data} 
					filterText={this.state.filterText}
				/>
			</div>
		);
	}
}

class SearchBar extends React.Component {
	handleChange() {
		// passing filter data up by using a callback
        this.props.onUserInput(
        	// ref is like the id
            this.refs.filterTextInput.getDOMNode().value
        );
    }
	render(){
		return (
            <form>
                <input 
                	type="text" 
                	placeholder="Search for one keyword..." 
                	ref="filterTextInput"
                	value= {this.props.filterText}
                	onChange= {this.handleChange.bind(this)} 
                />
            </form>
        );
	}
}

class Table extends React.Component {
	render(){
		let sections = [];
		let data = this.props.data;
		data.forEach(function(product){
			if (product.name.indexOf(this.props.filterText) === -1) {
				return;
			}
			sections.push(<Section data={product} />);
		}.bind(this))
		return(
			<div>{sections}</div>
		);
	}
}

class Section extends React.Component {
	render(){
		return(
			<div>
				<p>{this.props.data.name} = {this.props.data.price} </p>
			</div>
		);
	}
}
First of all we are importing react. Then we create the class SearchableTable which is a react component, that's why we extend the Component class from React. Notice this class has a 'export default' statement. This is ES6 for 'this class will be the exportable object in this file'. The class has a constructor, also a feature of ES6, where we define our component's state. Searchable table defines two child components, the searchbar and the table itself. The searchbar component will listen for changes, when there's a change it will fire the onUserInput callback it was given to by its parent (SearchableTable) which will update the state of the filterText variable. The table component dynamically creates sections of products based on the length of the array it is given to. However, if the product's name for a section is not in the current filter, it won't be rendered. The section component contains the structure for presenting the product's name and price.

Run it

You have everything now. All you need to do is run gulp on your terminal at the project's root. Wait while gulp sets up your web folder and for it to create the 'vendors.js' and 'bundle.js' files. It takes a while (5-10 seconds). If nothing happens, save your app.js file so the scripts task fires up. If there's something wrong in this article or you have trouble running the project. don't hesitate to comment! Finally, you can find the project in github. If you liked this tutorial, consider subscribing to my blog in order to get notified whenever I publish another article. No spam!
[wp_email_capture_form]    


Comments

3 responses to “How to get started with React js in ES6”

  1. Thanks for this! However I’m not completely satisfied with the error handling when I’m running my watch task, it logs out a huge js object making me have to scroll up in my terminal to see the actuall error. Not sure if it is babelify or browserify whos doing this. Do you have any tips on how to fix this?

    1. Jean-Pierre Sierens Avatar
      Jean-Pierre Sierens

      Hey dhallq

      Yeah it kind of bothers me as well but I have grown into it. I just did a quick search on other blogs and they are using the same configuration, I searched the docs on babel and I see no error logging options. If you find a solution let me know!

  2. prozbik Avatar
    prozbik

    with react-router iam get an error, bundle.js:1 Uncaught SyntaxError: Unexpected token function

Leave a Reply

Your email address will not be published. Required fields are marked *