タイトルの通り、こちらの公式チュートリアルをES6でやってみました。
https://facebook.github.io/react/docs/tutorial-ja-JP.html
また、チュートリアルでは React や Babel などを CDN で読み込んでいるためビルドは不要になってますが、
実際に開発するときは browserify なり webpack なりを使用したビルド環境が必要になると思うので
今回は webpack を使った開発環境の構築についても試してみました。
ソースコードはこちら:
同じことを既にやっている方がいて、環境構築手順とか webpack.config.js
の書き方とか
ほとんどこちらの記事の通りにさせていただきました。
大変参考になりました。
ReactのチュートリアルをES6で書いてwebpackとESLintも使ってみる - Qiita
簡易サーバーは Python で書いてます。
また、webpack.config.js
については整理してまた後日メモしようと思います。
React を ES6 で書くときの注意点とか
個人的にハマったというか勉強になったのは以下の2点ぐらいでしょうか。
1. getInitialState()
は ES6 の構文では使えない
参考:http://facebook.github.io/react/docs/reusable-components.html#es6-classes
The API is similar to
React.createClass
with the exception ofgetInitialState
. Instead of providing a separategetInitialState
method, you set up your ownstate
property in the constructor.
なので、かわりにコンストラクタ内で行います。
before (ES5)
var CommentBox = React.createClass({ getInitialState: function() { return {data: []}; }, // ...
after (ES6)
export default class CommentBox extends React.Component { constructor(props) { super(props); this.state = {data: []}; } // ...
ちなみに、今回のチュートリアルで登場しなかった propTypes
、defaultProps
についてはクラスの外で定義するようです。
before (ES5)
var Counter = React.createClass({ propTypes: { initialCount: React.PropTypes.number }, getDefaultProps: function() { return { initialCount: 0 }; }, // ...
after (ES6)
export default class Counter extends React.Component { // ... } Counter.propTypes = { initialCount: React.PropTypes.number }; Counter.defaultProps = { initialCount: 0 };
2. ES6 で書くときはインスタンスメソッドをbindする必要がある
これも公式ドキュメントに書いてあります。
参考:http://facebook.github.io/react/docs/reusable-components.html#no-autobinding
Methods follow the same semantics as regular ES6 classes, meaning that they don't automatically bind
this
to the instance. You'll have to explicitly use.bind(this)
or arrow functions=>
.
そして、この問題を回避するやり方はいくつかあるみたいです。
参考:Reactをes6で使う場合のbindの問題 - Qiita
コンストラクタで bind する以下のような方法もありますが
export class Counter extends React.Component { constructor(props) { super(props); this.state = {count: props.initialCount}; this.tick = this.tick.bind(this); // ここで bind } tick() { this.setState({count: this.state.count + 1}); } // ...
私は公式ドキュメントのサンプルコードにならって以下の書き方で統一することにしました。
export class Counter extends React.Component { constructor(props) { super(props); this.state = {count: props.initialCount}; } tick() { this.setState({count: this.state.count + 1}); } render() { return ( <div onClick={this.tick.bind(this)}> // ここで bind Clicks: {this.state.count} </div> ); } }
(2016/04/27追記)
Airbnb React/JSX Style Guide によるとコンストラクタで bind する方を推奨しているようです。
https://github.com/airbnb/javascript/tree/master/react#methods
Bind event handlers for the render method in the constructor. eslint: react/jsx-no-bind
Why? A bind call in the render path creates a brand new function on every single render.
ということから、パフォーマンスを考慮すると前者の方が良い...?