Using ES6 & ES* With React
Babel is not part of React. In fact, Babel’s purpose isn’t even that of a JSX transformer. Babel is a JavaScript compiler first. It takes ES* code and transforms it to run in browsers that don’t support ES* code. As of today, Babel mostly takes ES6 and ES7 code and transforms it into ES5 code. When doing these ECMAScript transformations it is trivial to also transform JSX expressions into React.createElement()
calls. This is what we examined in the previous section.
Given that Babel is the mechanism for transforming JSX, it allows you to write code that will run in future versions of ES*.
In the HTML page below the familiar HelloMessage
component has been rewritten to take advantage of ES6 classes. Not only is Babel transforming the JSX syntax, it is also transforming ES6 class syntax to ES5 syntax which can then be parsed by ES5 browser engines.
<!DOCTYPE html>
<html>
<head>
<script src="https://fb.me/react-15.2.0.js"></script>
<script src="https://fb.me/react-dom-15.2.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
class HelloMessage extends React.Component { //notice use of React.Component
render(){
return <div>Hello {this.props.name}</div>;
}
};
ReactDOM.render(<HelloMessage name="John" />, document.getElementById('app'));
/*** PREVIOUSLY ***/
/* var HelloMessage = React.createClass({
* render: function() {
* return <div>Hello {this.props.name}</div>;
* }
* });
*
* ReactDOM.render(<HelloMessage name="John" />, document.getElementById('app'));
*/
</script>
</body>
</html>
In the above HTML document Babel is taking in:
class HelloMessage extends React.Component {
render(){
return <div>Hello {this.props.name}</div>;
}
};
ReactDOM.render(<HelloMessage name="John" />, document.getElementById('app'));
And transforming it to this:
"use strict";
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var HelloMessage = (function (_React$Component) {
_inherits(HelloMessage, _React$Component);
function HelloMessage() {
_classCallCheck(this, HelloMessage);
_get(Object.getPrototypeOf(HelloMessage.prototype), "constructor", this).apply(this, arguments);
}
_createClass(HelloMessage, [{
key: "render",
value: function render() {
return React.createElement(
"div",
null,
"Hello ",
this.props.name
);
}
}]);
return HelloMessage;
})(React.Component);
;
ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), document.getElementById('app'));
Most ES6 features with a few caveats can be used when writing JavaScript that is transformed by Babel 5.8.23 (i.e., https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.js).
Notes
- Obviously one can could still use Babel for it’s intended purpose (i.e., compiling newer JavaScript code to older JavaScript code) without using JSX. However, most people using React are taking advantage of Babel for both unsupported ES* features and JSX transforming.
- Learn more about Babel by reading the Babel handbook.