React.jsチュートリアル覚書


* ずっとほっといてたReactをやっと触ってみた

# Reactとは
* JavaScriptライブラリ
* JavaScript内にHTMLタグ（のようなもの）を書ける
	* テンプレートエンジンのような感じ
* MVCのV部分のみ
* [公式チュートリアル](http://facebook.github.io/react/docs/tutorial.html)が充実してるのでこれを試す
	* web初心者には厳しい内容です

# ソースコード

* [github](https://github.com/AkihiroTakamura/node-react-tutorial)にこの内容のソースコードをおいています


# 開発環境
* 手っ取り早くサーバはnodeで。
* [以前投稿した手順](http://qiita.com/AkihiroTakamura/items/ac8fed6e44694c862800)を参考に。

# React開始

## Reactインストール

* npmより
* まずReact本体とreact-domを。これはセットで使う
* bootstrap使うなら```react-bootstrap```も一緒にinstall

```
npm install --save react react-dom react-bootstrap

```

* 次にbrowserifyにreactを認識させるため、```reactify```を入れる

```
npm install --save-dev reactify

```

## gulp調整

* browserifyにreactを認識させる
* ```transform```に```reactify```を追加

```gulpfile.js
gulp.task('js', function() {
  browserify({
    entries: ["./clientsrc/js/main.js"], // ビルド対象のファイル
    debug: true, // sourcemapを出力、chromeでのdebug可能にする
    transform: ['cssify', 'reactify']
  })
  .bundle()
  .on('error', console.error.bind(console)) // js compileエラーでもwatchを止めない
  .pipe(source("app.js")) // ビルド後のファイル名
  .pipe(buffer())
  .pipe(sourcemaps.init({loadMaps: true}))
  .pipe(uglify())
  .pipe(sourcemaps.write("./"))
  .pipe(gulp.dest("./public/js/")); // 生成先の指定
});

```

# React Tutorial

## Hello World

* お試しなのでmain.jsで記述
* ReactとReactDomをrequireする

```javascript
var React = require('react');
var ReactDom = require('react-dom');
```

* Reactのオブジェクト（コンポーネントという）は```React.createClass```を使って以下のように作成する
* 注意点としてcss class名の指定はhtmlと違い```className="xxx"```の形式

* 作ったコンポーネントをDOMに吐き出すには```ReactDom.render```を使う
* 中はコンポーネント名と吐き出し先DOM


***
* Reactに指定するtagはネスト可能
* ただしルートレベルは１つのタグのみ

* OKの例

```
<div>
  <div>
  </div>
</div>

```

* NGの例

```
<div>
</div>
<div>
</div>
```

***

* サンプルコード

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

  ReactDom.render(
    <CommentBox />,
    $('#example3').get(0)
  );

}

```

## JSXでの記述
* html tagでなくJSXでの記述も可能

```javascript
function example4() {
  var CommentBox = React.createClass({
    displayName: 'CommentBox',
    render: function() {
      return (
        React.createElement('div', {className: "commentBox"},
          "This Object Created by JSX"
        )
      )
    }
  });

  ReactDom.render(
    React.createElement(CommentBox, null),
    $('#example4').get(0)
  );

}

```

## コンポーネントのネスト

* コンポーネントはtag文字内で子オブジェクト名を指定することでネストできる
	* 子オブジェクトをソース上先に定義する必要がある

```javascript
function example5() {
  // 子コンポーネント１
  var CommentList = React.createClass({
    render: function() {
      return (
        <div className="commentList">
          Hello, I am a Comment List.
        </div>
      );
    }
  });

  // 子コンポーネント２
  var CommentForm = React.createClass({
    render: function() {
      return (
        <div className="commentForm">
          I am a CommentForm
        </div>
      );
    }
  });

  // 親コンポーネント
  var CommentBox = React.createClass({
    render: function() {
      return (
        <div className="commentBox">
          <h1>Example5</h1>
          <CommentList />
          <CommentForm />
        </div>
      )
    }
  });

  ReactDom.render(
    React.createElement(CommentBox, null),
    $('#example5').get(0)
  );

}


```


## コンポーネントへパラメータ渡し

* パラメータは親コンポーネントで指定した子コンポーネントのattrで渡せる
* パラメータ受け取りは```param.props.xxx```
* 親コンポーネントで指定した子コンポーネントの中身htmlは```param.props.children```で取得可能

```javascript
function example6() {
  var Comment = React.createClass({
    // get parameter by this.props from parent
    // this.props.[attributes name] - アトリビュートにセットされたパラメータ
    // this.props.children - タグの子要素
    render: function() {
      return (
        <div className="comment">
          <h2 className="commentAuthor">
            {this.props.author}
          </h2>
          {this.props.children}
        </div>
      );
    }
  });

  var CommentList = React.createClass({
    render: function() {
      return (
        <div className="commentList">
          <Comment author="Akihiko Takayama">This is one comment</Comment>
          <Comment author="Akemi Takayama">This is another comment</Comment>
        </div>
      );
    }
  });

  // 子コンポーネント２
  var CommentForm = React.createClass({
    render: function() {
      return (
        <div className="commentForm">
          I am a CommentForm
        </div>
      );
    }
  });

  // 親コンポーネント
  var CommentBox = React.createClass({
    render: function() {
      return (
        <div className="commentBox">
          <h1>Example6</h1>
          <CommentList />
          <CommentForm />
        </div>
      )
    }
  });

  ReactDom.render(
    React.createElement(CommentBox, null),
    $('#example6').get(0)
  );

}

```

## コンポーネントへ動的パラメータ渡し

* 親コンポーネントに外部からのデータオブジェクトを渡す
* コンポーネント内で受け取ったデータを使って動的にhtmlを構成

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

  var CommentList = React.createClass({
    render: function() {
      // 受け取ったデータ分、Commentオブジェクトを作成
      var commentNodes = this.props.data.map(function(comment) {
        return (
          <Comment author={comment.author} key={comment.id}>
            {comment.text}
          </Comment>
        );
      });
      return (
        <div className="commentList">
          {commentNodes}
        </div>
      );
    }
  });

  // 子コンポーネント２
  var CommentForm = React.createClass({
    render: function() {
      return (
        <div className="commentForm">
          I am a CommentForm
        </div>
      );
    }
  });

  // 親コンポーネント
  var CommentBox = React.createClass({
    render: function() {
      return (
        <div className="commentBox">
          <h1>Example7</h1>
          <CommentList data={this.props.data} />
          <CommentForm />
        </div>
      )
    }
  });

  var data = [
    {id: 1, author: "Akihiko Takayama", text: "Akiiko's Comment"},
    {id: 2, author: "Akemi Takayama", text: "Akemi's Comment"}
  ];

  ReactDom.render(
    React.createElement(CommentBox, {data: data}),
    $('#example7').get(0)
  );

}


```


## コンポーネントへajax渡し
* 正直ここまでreactにやらせると制御きつい気がするので割愛
* 続きは[公式をみてください](http://facebook.github.io/react/docs/tutorial.html#fetching-from-the-server)


# 触ってみた所感
* フロントエンド側のテンプレートエンジンと割り切ると気楽につかえて◯
	* angularのように縛り一杯でないあたりとか
	* jQueryでガチガチ書く人はとっつきやすいはず
* 今まで```jquery multiline```とかでやってたのの代わりにできそう
* テンプレートいっぱい作ってexportsしといて使うスタイルまで昇華できれば
* どこまでコンポーネント化するか、設計方針ちゃんと決めとく必要ありそう