【個人メモ】React Tutorialをちょこっとやってみた

# React

[React](http://facebook.github.io/react)が最近騒がれてるので、
よくわからないから[Reactjs tutorial](http://facebook.github.io/react/docs/tutorial.html)を少しこなしてみた。

## Reactとは

ぐぐるとmizchiさんのブログエントリが出てくる。

[Facebook製リアクティブプログラミングライブラリ React を試してみた + 感想](http://mizchi.hatenablog.com/entry/2014/01/01/234435)

VirtualDOMという技術を使っているようだ。

[[JavaScript] 仮想DOMを提供する『React』について少し調べてみた](http://qiita.com/hkusu/items/ee5bc75c3c32185c7b76)

VirutalDOMだけ切り出した成果物も存在する。

https://github.com/Matt-Esch/virtual-dom
[Virtual DOMのアルゴリズムが知りたくてvirtual-domのコードを読んだ話](http://saneyukis.hatenablog.com/entry/2014/09/03/134858)

# react-toolsのインストール

React、type=“text/jsx” なコンテンツについてXHRで取りに行くようだ。
Chromeで開発することが多い、というかDeveloper tool入れたし、
開発中何かしらサーバ立ててやるのがよいのだろうか、と思ったけど
JSXをjsにコンパイルするのが楽そうだ。

JSXにプリコンパイルするものがあるようだ。
console.logで一つ一つ出てくるのは親切だな。

```
npm install -g react-tools
```

jsxというコマンドラインツールがインストールされる。

## jsxコマンド

jsxで書かれたものをjava scriptとしてコンパイルする。
jsx形式で書かれたファイルはsrcディレクトリに置いて、
javascript形式にコンパイルされたファイルをdestディレクトリに吐出されるようにする。

```
jsx --watch src/ dest/
```

# 初歩

初歩として、このような形になった。

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"/>
    <title>React js tutorial</title>
    <script src="http://fb.me/react-0.12.0.js"></script>
    <script src="http://fb.me/JSXTransformer-0.12.0.js"></script>
    <script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
  </head>
  <body>
    <div id="content"></div>
    <script src="./dest/main.js"></script>
  </body>
</html>
```

- main.jsは以下のとおり。

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

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

- レンダリング結果。

![Screen Shot 2014-11-02 at 00.12.58.png](https://qiita-image-store.s3.amazonaws.com/0/3985/a4757d21-2dfc-497a-34ca-34fb07f689a8.png)


<CommentBox />の内容はCommentBox(Reactのインスタンス)の内容が展開されて、
DOMが構築されるんだなあ。

このまま進めていってみよう。

```html
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() {
    return (
      <div className="commentList">
        <Comment author="Pete Hunt">This is one comment</Comment>
        <Comment author="Jordan Walke">This is *another* comment</Comment>
      </div>
    );
  }
});

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

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

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

CommentListの中で、Commentを使っている。
Commentの定義は以下のとおりになっている。

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

```html
return (
  <div className="commentList">
    <Comment author="Pete Hunt">This is one comment</Comment>
    <Comment author="Jordan Walke">This is *another* comment</Comment>
  </div>
);
```

CommentList内で、Commentを構築しているが、
author Attribute及びThis is one commentなど
**this.props.author**と**this.props.children**で
引っ張るようにしているのか。

this.propsのpropsは[propertiesの略](http://facebook.github.io/react/docs/displaying-data.html#reactive-updates)で、Componentに包み込んだ(内包した)Componentの内容を呼び出したい場合に利用するようだ。

# JSON形式で表現したデータをComponentで利用する

JSON形式のデータをComponent内で利用することもできるようだ。
[Showdown.jsを利用し、Markdown形式のパースを行う形になっているセクション](http://facebook.github.io/react/docs/tutorial.html#adding-markdown)があるが、
そこが気になった。

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"/>
    <title>React js tutorial - Markdown -</title>
    <script src="http://fb.me/react-0.12.0.js"></script>
    <script src="http://fb.me/JSXTransformer-0.12.0.js"></script>
    <script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/showdown/0.3.1/showdown.min.js"></script>
  </head>
  <body>
    <div id="content"></div>
    <script src="./dest/main.js"></script>
  </body>
</html>
```

```html
var converter = new Showdown.converter();

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

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

var CommentList = React.createClass({
  render: function() {
    var commentNodes = this.props.data.map(function(comment){
      return (
        <Comment author={comment.author}>
          {comment.text}
        </Comment>
        );
    });
    return (
      <div className="commentList">
        {commentNodes}
      </div>
    );
  }
});

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

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

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


data Objectの内容をCommentBox Componentで展開し、
レンダリングすることがわかった。

# サーバ側と通信し、コメントを保存する


comments.jsonファイルにdataの内容を保存する

もっとTutorialを進めていくと
comments.sonにコメントを追加する内容になる。
サーバ側でcomments.jsonを配信しなければならないので、
react-tutorial リポジトリから
サーバとサンプルファイル一式をgit cloneして手元に持ってくることにした。


https://github.com/reactjs/react-tutorial

```
> git clone git@github.com:reactjs/react-tutorial.git
> cd react-tutorial
> python server.py
> open http://localhost:3000/index.html
```

![bbee745a-ec1c-d114-fb49-5d6a38ac2e10.png](https://qiita-image-store.s3.amazonaws.com/0/3985/23c19d09-8268-4fa4-11bb-044b8f2360a2.png)


Your nameとSay something…を追加していく

![835ffd48-a1b9-f857-fa07-6d21bf20a024.png](https://qiita-image-store.s3.amazonaws.com/0/3985/37e81f0d-22db-5661-4f31-617e28e39338.png)

更新された。
が、react-tutorialにあるserver.pyだと、
_comments.jsonファイルへの更新は含まれていないので、ちょこっと改造する


```diff
diff --git server.py server.py
index 7edb6f6..7ffda64 100644
--- server.py
+++ server.py
@@ -47,6 +47,8 @@ class MyHandler(SimpleHTTPRequestHandler):

             # Save the data
             comments.append({u"author": form.getfirst("author"), u"text": form.getfirst("text")})
+            with open('_comments.json', 'w') as f:
+                f.write(json.dumps(comments))
             sendJSON(self)
         else:
             SimpleHTTPRequestHandler.do_POST(self)
```


_comments.jsonにファイルが保存される形にしてみた。

```
> python server.py
> open http://localhost:3000/index.html
```

ページを開いた後、保存を繰り返し、

![9055d6ad-9b3f-f375-ea62-757d46a0d20a.png](https://qiita-image-store.s3.amazonaws.com/0/3985/37a7be7a-81f6-73a3-694e-b3286ab6b981.png)

サーバを止めて、再起動する。
**_comments.json**には、入力した内容が保存されている


```json
[{"text": "Hey there!", "author": "Pete Hunt"}, {"text": "fufafuga", "author": "hogehoge"}, {"text": "uooo", "author": "mogemoge"}]
```

JSXの概念や、React.jsの使い方とか、
なんとなーくわかってきたような。

サーバサイドレンダリングとか、まだわかってないところばかりなので
いじっていこう。

https://github.com/petehunt/react-server-rendering-example
https://github.com/mhart/react-server-example