react.js

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

More than 1 year has passed since last update.

公式

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

準備

まずはチュートリアル用のリポジトリを公式からcloneしてパッケージをインストールする。
ここにReactから接続するための簡易サーバが用意されているので、ありがたく使わせてもらう。

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

自分で書いたコードを実行させたいので、
/public/index.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のコンポーネントを作ってみる。

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と組み合わせる。

CommentListCommentFormの追加

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のアップデート

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から渡ってくるデータを受け取っている。

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}のように書くことでテキストやコンポーネントを差し込むことができる。

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

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')
);
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) へ続く。