Reactまとめ - QUICK START - ①

- [Getting Started](http://facebook.github.io/react/docs/getting-started.html)
- [Tutorial - Hook up the data model](http://facebook.github.io/react/docs/tutorial.html#hook-up-the-data-model) 

までのまとめ

# Getting Started

## 実行環境
- [React JSFiddle](http://jsfiddle.net/reactjs/69z2wepo/)
- [React JSFiddle without JSX](http://jsfiddle.net/reactjs/5vjqabv3/)
- [Starter Kit Download](http://facebook.github.io/react/downloads/react-0.12.2.zip)

## JSXについて
- 簡単に言うと`Javascriptのコード中に記述できるXMLライクなシンタックス`
- JSXを含むスクリプトの読み込みにはタイプ属性`jsx/text`を使用
- `JSXTransformer.js`モジュールを使用して、ブラウザ上で`jsx` -> `js`へ翻訳
- `react-tools`を使ってあらかじめ[コンパイル](http://facebook.github.io/react/docs/getting-started.html#offline-transform)しておけば、通常のjsファイルとして読み込み可能
- JSXについての詳細
 - [JSX in Depth](http://facebook.github.io/react/docs/jsx-in-depth.html)
 - [Draft: JSX Specification](http://facebook.github.io/jsx/)

#Tutorial

- `React.createClass()`により新規のReactコンポーネントを生成
- Reactコンポーネントの`render()`はツリー化されたReactコンポーネント群を返し、これはHTMLのレンダリングに使用される。
- `render()`内にある`div`タグは実際のDOMではなく、React用divコンポーネントのインスタンス
- ReactはHTML文字列を生成しないので、デフォルトでXSSに対応
- `React.render()`はルートコンポーネントをインスタンス化し、第二引数に指定された生のDOMに挿入
- JSXは名前空間の汚染を防止するため、コンパイル時にHTMLタグをすべてReact.createElement(tagName)に置き換える。

```html:ベースのHTML
<html>
  <head>
    <title>Hello React</title>
    <script src="http://fb.me/react-0.12.2.js"></script>
    <script src="http://fb.me/JSXTransformer-0.12.2.js"></script>
    <!-- jqueryは必須ではない -->
    <script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
  </head>
  <body>
    <div id="content"></div>
    <script type="jsx/text">
      //サンプルコード
    </script>
  </body>
</html>
```

```js:JSX
//Reactコンポーネントの生成
var CommentBox = React.createClass({
    render: function() {
      return (
        <div className="commentBox">
          Hello, world! I am a CommentBox.
        </div>
     );
   }
});

React.render(
  <CommentBox />,
  document.getElementById('content')
);
```

```js:JS
//Reactコンポーネントの生成
var CommentBox = React.createClass({
    render: function() {
      return (
        React.createElement('div', {className: "commentBox"},
          "Hello, world! I am a CommentBox."
        )
     );
   }
});

React.render(
  React.createElement(CommentBox, null),
  document.getElementById('content')
);
```

- `props`（propertiesの略）を利用してデータを受け渡す。
- コンポーネントタグの属性にプロパティをセット
- 指定されたプロパティは、コンポーネント側から`this.props.属性名`で取得できる（JSXの場合は`{}`で囲む）。

```js:JSX
var CommentList = React.createClass({
  render: function() {
    return (
      <div className="commentList">
        //Commentコンポーネントのプロパティにセットされる値
        //this.props.author = 'Pete Hunt'
        //this.props.children = 'This is one comment'
        <Comment author="Pete Hunt">This is one comment</Comment>
        //Commentコンポーネントのプロパティにセットされる値
        //this.props.author = 'Jordan Walke'
        //this.props.children = 'This is *another* comment'
        <Comment author="Jordan Walke">This is another comment</Comment>
      </div>
    );
  }
});

var Comment = React.createClass({
  render: function() {
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author} //CommentListでセットしたauthorを取得
        </h2>
        {this.props.children} //CommentListでセットしたchildrenを取得
      </div>
    );
  }
});

var CommentBox = React.createClass({displayName: 'CommentBox',
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList />
      </div>
    );
  }
});

React.render(
  <CommentBox />,
  document.getElementById('content')
);
```


```js:JS
var CommentList = React.createClass({
  render: function() {
    return (
      React.createElement(
        'div',
        {className: 'commentList'},
        //Commentコンポーネントのプロパティにセットされる値
        //this.props.author = 'Pete Hunt'
        //this.props.children = 'This is one comment'
        React.createElement(Comment, {author: 'Pete Hunt'}, 'This is one comment'),
        //Commentコンポーネントのプロパティにセットされる値
        //this.props.author = 'Jordan Walke'
        //this.props.children = 'This is *another* comment'
        React.createElement(Comment, {author: 'Jordan Walke'}, 'This is another comment')
      )
    );
  }
});

var Comment = React.createClass({
  render: function() {
    return (
      React.createElement(
        'div',
        {className: 'comment'},
        React.createElement(
          'h2',
          {className: 'commentAuthor'},
          this.props.author //CommentListでセットしたauthorを取得
        ),
        this.props.children //CommentListでセットしたchildrenを取得
      )
    );
  }
});

var CommentBox = React.createClass({displayName: 'CommentBox',
  render: function() {
    return (
      React.createElement(
        'div',
        {className: "commentBox"}, 
        React.createElement('h1', {}, 'Comments'),
        React.createElement(CommentList)
      )
    );
  }
});

React.render(
  React.createElement(CommentBox),
  document.getElementById('content')
);
```

- ルートコンポーネントから外部データを各コンポーネントに受け渡す場合も、コンポーネントタグの属性に値をセットして、コンポーネント側で`props`から取得できる。

```js:JSX
var data = [
  {author: "Pete Hunt", text: "This is one comment by json"},
  {author: "Jordan Walke", text: "This is another comment by json"}
];

var CommentList = React.createClass({
  render: function() {
    //CommentBoxから受け取ったデータをCommentタグにループでセット
    var commentNodes = this.props.data.map(function (comment) {
      return (
        <Comment author={comment.author}>
          {comment.text}
        </Comment>
      );
    });
    return (
      <div className="commentList">
        {commentNodes}
      </div>
    );
  }
});

var Comment = React.createClass({
  render: function() {
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author}
        </h2>
        {this.props.children}
      </div>
    );
  }
});

var CommentBox = React.createClass({displayName: 'CommentBox',
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        //ルートコンポーネントから受け取ったデータをCommentListタグにセット
        <CommentList data={this.props.data} /> 
      </div>
    );
  }
});

React.render(
  <CommentBox data={data} />, //jsonデータをセット
  document.getElementById('content')
);
```

```js:JS
var data = [
  {author: "Pete Hunt", text: "This is one comment by json"},
  {author: "Jordan Walke", text: "This is another comment by json"}
];

var CommentList = React.createClass({
  render: function() {
　　//CommentBoxから受け取ったデータをCommentタグにループでセット
    var commentNodes = this.props.data.map(function (comment) {
      return (
        React.createElement(Comment, {author: comment.author}, comment.text)
      )
    });
    return (
      React.createElement(
        'div',
        {className: 'commentList'},
        commentNodes
      )
    );
  }
});

var Comment = React.createClass({
  render: function() {
    return (
      React.createElement(
        'div',
        {className: 'comment'},
        React.createElement(
          'h2',
          {className: 'commentAuthor'},
          this.props.author
        ),
        this.props.children
      )
    );
  }
});

var CommentBox = React.createClass({displayName: 'CommentBox',
  render: function() {
    return (
      React.createElement(
        'div',
        {className: "commentBox"}, 
        React.createElement('h1', {}, 'Comments'),
        //ルートコンポーネントから受け取ったデータをCommentListタグにセット
        React.createElement(CommentList, {data: this.props.data})
      )
    );
  }
});

React.render(
  React.createElement(CommentBox, {data: data}),//jsonデータをセット
  document.getElementById('content')
);
```

## 次回
[Tutrial - Reactive state](http://facebook.github.io/react/docs/tutorial.html#reactive-state)

# 参考
[React](http://facebook.github.io/react/index.html)
[React (Virtual) DOM Terminology](https://gist.github.com/sebmarkbage/fcb1b6ab493b0c77d589#react-elements)