初めてのReact.js


#React.jsでHelloWorld〜フォームの送信まで

##React.jsでHello Worldを表示させる

```html
<!-- index.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>React.js 初めの1歩</title>

    <!-- 下記のJSを使えばReact.jsの環境は作れるので入れる -->
    <script src="https://npmcdn.com/react@15.3.0/dist/react.js"></script>
    <script src="https://npmcdn.com/react-dom@15.3.0/dist/react-dom.js"></script>
    <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script>
    <!-- 今回は使わない --> 
    <script src="https://npmcdn.com/jquery@3.1.0/dist/jquery.min.js"></script>
    <script src="https://npmcdn.com/remarkable@1.6.2/dist/remarkable.min.js"></script>  
  </head>
  <body>
    //React.jsで生成するHTML要素を挿入する場所
    <div id="content"></div>
    
    //JSタグの中に書いていく.
    <script type="text/babel">
      
      // Reactにおけるコンポーネントの作成(オブジェクト)
      var SampleBox = React.createClass({
        render: function() {
          return (
            <div className="sampleBox">
              <h1>初めてのReact.js</h1>
              <div>Hello, World!</div>
            </div>
          );
        }
      });
      
      //ReactDOM.render()
      //第一引数..renderメソッドをもったコンポーネント(オブジェクト)を渡す
      //第二引数..renderする位置を指定する
      ReactDOM.render(
        <SampleBox />,
        document.getElementById('content')
      );
    </script>
  </body>
</html>
```

##＊複数のComponentを渡すことができないため、最終的に1つにまとめる必要がある。
###NG例
```html
  <body>
    <div id="content"></div>

    <script type="text/babel">      
      var SampleBox = React.createClass({
        render: function() {
          return (
            //一番上の親要素が1つではないのでNG! :disappointed_relieved: 
            **<h1>初めてのReact.js</h1>**     
            **<div>Hello, World!</div>**
          );
        }
      });
      ReactDOM.render(
        <SampleBox />,
        document.getElementById('content')
      );
    </script>
  </body>

```


##動的に親要素内に子要素を追加する

```html
  <body>
    <div id="content"></div>
    <script type="text/babel">
      var ParentBox = React.createClass({
        render: function() {
          return (
            <div className="firstBox">
              <h1>初めてのReact.js</h1>
              <ChildBox />                　　　　　　　//ChildBoxのRenderメソッドの中身を呼び出し
            </div>
          );
        }
      });
      
　　　　　　　　　　　//子要素の作成
      var ChildBox = React.createClass({
        render: function() {
          return (
            <ul className="secondBox">
              <li>初めてのReact.js</li>
              <li>Hello, World!</li>
            </ul>
          );
        }
      });

      ReactDOM.render(
        <ParentBox />,
        document.getElementById('content')
      );

    </script>
  </body>
```

##パラメーターのセットと表示(prop)
```html
  <body>
    <div id="content"></div>
    <script type="text/babel">

      var ParentBox = React.createClass({
        render: function() {
          return (
            <div className="firstBox">
              <h1>初めてのReact.js</h1>
              //パラメーターを用意
              <ChildBox num="1" title="初めてのReact.js" word="Hello, World!"></ChildBox>
              <ChildBox num="2" title="2回目のReact.js" word="Hello, World2!"></ChildBox>
            </div>
          );
        }
      });
      
      var ChildBox = React.createClass({
        render: function() {
          return (
            <div className="secondBox">
              //取得したパラメーターを表示
              <p>要素{this.props.num}</p>
              <ul>
                <li>{this.props.title}</li>
                <li>{this.props.word}</li>
              </ul>
            </div>
          );
        }
      });

      ReactDOM.render(
        <ParentBox />,
        document.getElementById('content')
      );

    </script>
</body>
```

##可変なパラメーターと不可変なパラメーターの扱い方(propとstate)

```html
  <body>
    <div id="content"></div>

    <script type="text/babel">

      var ParentBox = React.createClass({
        //stateの初期化
        getInitialState() {
          return {
            articles: [
              {"num": 1, "title": "初めてのReact.js", "word": "Hello, World!"},
              {"num": 2, "title": "2回目のReact.js", "word": "Hello, World2!"}
            ]
          }
        },
        render: function() 
　　　　　　　　　　　　　　　　　　　　// articlesというstateの中身を受け取って、展開する
          // DOMに反映する時にこの値が参照され、最小限の変更にするために行う
          // ちなみにDev環境でkeyを指定しないとコンソールにエラーがでる
　　　　　　　　　　　　　　　　　　　　var articles = this.state.articles.map((article) => {
            return <ChildBox num={article.num} key={article.num} title={article.title} word={article.word}/>
          });
          return (
            <div className="firstBox">
              <h1>初めてのReact.js</h1>
              {articles}
            </div>
          );
        }
      });
      
      var ChildBox = React.createClass({
        render: function() {
          return (
            <div className="secondBox">
              <p>要素{this.props.num}</p>
              <ul>
                <li>{this.props.title}</li>
                <li>{this.props.word}</li>
              </ul>
            </div>
          );
        }
      });

      ReactDOM.render(
        <ParentBox />,
        document.getElementById('content')
      );

    </script>
  </body>
```
## jsonファイルからデータを取り出し表示する
```html
<body>
    <div id="content"></div>

    <script type="text/babel">
      var ParentBox = React.createClass({
        // JsonファイルをAjaxでリクエストを送り、Jsonの中身をstateに入れる
        //  ReactDOM.renderで、リクエストの送り先をPROP
        getJson: function() {
          $.ajax({
            url: this.props.url,
            dataType: 'json',
            cache: false,
            success: function(articles) {
              this.setState({articles: articles});
            }.bind(this),
            error: function(xhr, status, err) {
              console.error(this.props.url, status, err.toString());
            }.bind(this)
          });
        },
        getInitialState() {
          return {
            articles: []
          }
        },
        componentDidMount: function() {
          //getJsonを呼び出す
          this.getJson();
          // 2秒ごとにgetJsonを動かす設定
          setInterval(this.getJson, this.props.pollInterval);
        },
        render: function() {
          var articles = this.state.articles.map((article) => {
            return <ChildBox num={article.num} key={article.num} title={article.title} word={article.word}/>
          });
          return (
            <div className="firstBox">
              <h1>React.js 初めの1歩</h1>
              {articles}
            </div>
          );
        }
      });
      
      var ChildBox = React.createClass({
        render: function() {
          return (
            <div className="secondBox">
              <h2>{this.props.title}</h2>
              <p>要素{this.props.num}</p>
              <p>{this.props.word}</p>
            </div>
          );
        }
      });
      //propにリクエストURLとIntervalの時間を設定
      ReactDOM.render(
        <ParentBox url="sample.json" pollInterval={2000} />,
        document.getElementById('content')
      );

    </script>
  </body>
```

#フォームで投稿した値をstateに入れて保持する

```html
  <body>
    <div id="content"></div>
    <script type="text/babel">
      var ParentBox = React.createClass({
        //ParentBoxで生成したURLのpropにJson取得リクエストを送る
        getJson: function() {
          $.ajax({
            url: this.props.url,
            dataType: 'json',
            cache: false,
            success: function(articles) {
              // 取得した内容をstateにぶちこむbutikomu
              this.setState({articles: articles});
            }.bind(this),
            error: function(xhr, status, err) {
              console.error(this.props.url, status, err.toString());
            }.bind(this)
          });
        },
        // フォームで送信された内容を state articles に追加し、state articles を再構築
        handleArticleSubmit: function(article) {
          //現在の state articlesを取得
          var articles = this.state.articles;
          // 適当にid と numを追加 
          article.id = Date.now();
          article.num = Date.now();

          // フォームで送信された値を 追加
          var newArticles = articles.concat([article]);
          // state に再追加
          this.setState({articles: newArticles});
          //　TODO DBに入れる場合、ここにPOSTのリクエストを書く
        },
        getInitialState() {
          return {
            articles: []
          }
        },
        componentDidMount: function() {
          this.getJson();
          // Jsonファイルを見に行き、フォームで送信した値が消えるためコメントアウト
          //setInterval(this.getJson, this.props.pollInterval);
        },
        render: function() {
          var articles = this.state.articles.map((article) => {
            return <ChildBox num={article.num} key={article.num} title={article.title} word={article.word}/>
          });
          return (
            <div className="firstBox">
              <h1>React.js 初めの1歩</h1>
              {articles}
              <ArticleForm onArticleSubmit={this.handleArticleSubmit}/>
            </div>
          );
        }
      });
      
      var ChildBox = React.createClass({
        render: function() {
          return (
            <div className="secondBox">
              <h2>{this.props.title}</h2>
              <p>要素{this.props.num}</p>
              <p>{this.props.word}</p>
            </div>
          );
        }
      });

      var ArticleForm = React.createClass({
        getInitialState: function() {
          return {title: '', word: ''};
        },
        handleTitleChange: function(e) {
          this.setState({title: e.target.value});
        },
        handleWordChange: function(e) {
          this.setState({word: e.target.value});
        },
        handleSubmit: function(e) {

          // 入れないとページのリロードが走る
          e.preventDefault();
          
          // 空白を消す
          var title = this.state.title.trim();
          var word = this.state.word.trim();
          
          // バリデーションはここで行う
          if (!word || !title) {
            return;
          }
          this.props.onArticleSubmit({title: title, word: word});
          // テキストフィールドに保持していた stateを消す
          this.setState({title: '', word: ''});
        },
        render: function() {
          return (
            <form className="articleForm" onSubmit={this.handleSubmit}>
              <input type="text" placeholder="タイトル" value={this.state.title} onChange={this.handleTitleChange}/>
              <input type="text" placeholder="本文" value={this.state.word} onChange={this.handleWordChange}/>
              <input type="submit" value="Post" />
            </form>
          );
        }
      });     

      ReactDOM.render(
        <ParentBox url="sample.json" pollInterval={2000} />,
        document.getElementById('content')
      );

    </script>
  </body>
```

###参考記事

React チュートリアル
https://facebook.github.io/react/docs/tutorial-ja-JP.html

React.jsのProp
http://qiita.com/koba04/items/bc13d1f42964278ae14e

React.js + CSS
http://qiita.com/koba04/items/0e81a04262e1158dbbe4

React.jsのComponent Lifecycle
http://qiita.com/koba04/items/66e9c5be8f2e31f28461