React.jsチュートリアルをやる(1)


## 公式
公式のチュートリアルは日本語のページもあったけど、自分には少し読みにくかったので英語の方でやった。
ja : https://facebook.github.io/react/docs/tutorial-ja-JP.html
en : https://facebook.github.io/react/docs/tutorial.html

## 準備
まずはチュートリアル用のリポジトリを[公式](https://github.com/reactjs/react-tutorial)からcloneしてパッケージをインストールする。
ここにReactから接続するための簡易サーバが用意されているので、ありがたく使わせてもらう。

```zsh
$ git clone https://github.com/reactjs/react-tutorial.git
$ cd react-tutorial
$ npm install
```

自分で書いたコードを実行させたいので、
`/public/index.html`を開いて下記のように書き換える。

```html:index.html
<!-- index.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>React Tutorial</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.5/marked.min.js"></script>
  </head>
  <body>
    <div id="content"></div>
    <script type="text/babel">
      // To get started with this tutorial running your own code, simply remove
      // the script tag loading scripts/example.js and start writing code here.
    </script>
  </body>
</html>
```
今回は`<script type="text/babel"></script>`の中にreactのコードを書いていく。

## コンポーネント
Reactはコンポーネント単位で処理を記述していく。
今回作るコメント投稿フォームは下記のようなコンポーネント構造をとる。

```
- CommentBox
  - CommentList
    - Comment
  - CommentForm
```
まずは`CommentBox`のコンポーネントを作ってみる。

```js
var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
        Hello, world! I am a CommentBox.
      </div>
    );
  }
});
ReactDOM.render(
  <CommentBox />,
  document.getElementById('content')
);
```
HTMLのエレメントはローワーキャメルケース、Reactクラスはアッパーキャメルケースで書く。

### DOMっぽいシンタックスシュガー
また、

```
return (
  <div className="commentBox">
    Hello, world! I am a CommentBox.
  </div>
);
```
はJSXのシンタックスシュガーで、DOMをそのままjsコードの中に記述できるようになっている。ただこれをそのまま実行するとjsの実行エラーになるので、実行する前にコンパイルする必要がある。
コンパイルしてくれるのは先ほどの`index.html`の中に記述した
`    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>`。

先ほどのコードがコンパイルされると

```
return (
  React.createElement('div', {className: "commentBox"},
  "Hello, world! I am a CommentBox."
  )
);
```
のようになり、jsコードとして正常に実行される。

### そもそも何をしているのか
`React.createClass`関数でコンポーネントを生成して、その引数として渡しているオブジェクトの`render`関数の中でDOMを定義している。で、ここで定義されたDOMがコンポーネントとして利用される。ここで定義するDOMはあくまでReactのdivインスタンスで、実際のDOMとは違う。最終的にDOMに変換されるReactのdivインスタンス。

`ReactDOM.render`は、フレームワークの起動とルートコンポーネント(ここでは`CommentBox`)のインスタンス化を行っている。

## コンポーネントを組み合わせる
`CommentList`コンポーネントと`CommentForm`コンポーネントを作って`CommentBox`と組み合わせる。

`CommentList``CommentForm`の追加

```js
var CommentList = React.createClass({
  render: function() {
    return (
      <div className="commentList">
        Hello, world! I am a CommentList.
      </div>
    );
  }
});

var CommentForm = React.createClass({
  render: function() {
    return (
      <div className="commentForm">
        Hello, world! I am a CommentForm.
      </div>
    );
  }
});
```
`CommentBox`のアップデート

```diff
var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
-       Hello, world! I am a CommentBox.
+       <h1>Comments</h1>
+       <CommentList />
+       <CommentForm />
      </div>
    );
  }
});
```
このように書くことで、DOMを構造化できる。


### props(property)を使う
Reactでは、子コンポーネントから親コンポーネントのデータをプロパティとして受け継ぐことができる。プロパティは子コンポーネントの中で`this.props`を通して取得する。
ここでは`Comment`コンポーネントを新しく作り、`CommentList`から渡ってくるデータを受け取っている。

```js
var Comment = React.createClass({
  render: function() {
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author}
        </h2>
        {this.props.children}
      </div>
    );
  }
});
```
DOMツリー(JSX)の中で`{this.props.children}`のように書くことでテキストやコンポーネントを差し込むことができる。

次に親コンポーネントから子コンポーネントへデータを渡す。

```diff
var data = [
  {id: 1, author: "Pete Hunt", text: "This is one comment"},
  {id: 2, author: "Jordan Walke", text: "This is *another* comment"}
];

var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
-       <CommentList />
+       <CommentList data={this.props.data} />
        <CommentForm />
      </div>
    );
  }
});

ReactDOM.render(
- <CommentBox />,
+ <CommentBox data={data} />,
  document.getElementById('content')
);
```

```diff
var CommentList = React.createClass({
  render: function() {
    var commentNodes = this.props.data.map(function(comment) {
      return (
-       <div className="commentList">
-         Hello, world! I am a CommentList.
-       </div>
+       <Comment author={comment.author} key={comment.id}>
+         {comment.text}
+       </Comment>
      );
    });
    return (
      <div className="commentList">
        {commentNodes}
      </div>
    );
  }
});
```

これでデータの受け渡しができた。

(1)はここまで。[React.jsチュートリアルをやる(2)](http://qiita.com/saekis/items/596aad5a239a597ed4f5) へ続く。