はじめに

キャスレーコンサルティング株式会社 SI(システム・インテグレーション)部の松本(卓)と申します。
今回は、フロントエンド開発で使用されている「React.js」の入門編としてご紹介したいと思います。

React.jsについて

React.jsとは、Facebookが開発したWebサイト上のUIパーツを構築するためのJavascriptライブラリです。
Facebookで使用されているのはもちろんのこと、Yahoo!のページなどでも使用されています。

Reactの3つの特徴

  1. Declarative : 宣言的な
  2. Component Based : コンポーネントベースである
  3. Learn Once,Write AnyWhere : 一度覚えてしまえばどこにだって書ける

以上の3つが、大きな特徴となっています。

Reactのウリ

  • レンダリングが早い!ということ
  • 管理しやすい!ということ

詳しい説明は省きますが、優れている点として上記を覚えておくといいでしょう。

Reactの基本的な文法

下記は、ReactでのHello Casley!出力プログラムになります。
下記をコピーし、htmlファイルで保存しブラウザで表示を確認してみましょう!

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello Casley</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
  </head>
  <body>
    <div id="main"></div>
    <script>
      ReactDOM.render(React.DOM.h1(null,'Hello Casley!'),
      document.getElementById('main'));
    </script>
  </body>
</html>

・出力結果

Hello Casley!

Reactは前述のとおり「ライブラリ」のため、scriptタグでincludeするだけで使用することができます。
今回は、CDN経由で関連するファイルを読み込み使用します。

React.jsファイルはReactの基本的な内容を提供するJSファイルとなり、
React-DOM.jsファイルは、DOM操作をするためのJSとなります。

この2ファイルは、セットで使用するものだと覚えておくといいでしょう。

Reactの基礎:コンポーネントについて

Reactの3つの大きな特徴としてあげた「コンポーネント」について説明します。
コンポーネントとは、一般的なIT用語でいうとソフトウェアやシステムを構成する部品や要素のことです。

Reactでも「UIを構成する部品や要素」を意味します。
Reactのコンポーネントは、ページを構成する部品 = HTMLを表現するための部品ともいえます。
Reactではコンポーネントを定義し、それを組み合わせることで画面を作成していきます。

<script>
  ReactDOM.render(React.DOM.h1(null,'Hello Casley!'), document.getElementById('main'));
</script>

上記のソースは、序盤に出てきたHello Casley!を表示するソースになります。
ReactDOM.render(第一引数、第二引数)というメソッドを使用して、コンポーネントを画面表示します。

第一引数にはコンポーネントから作成するHTML要素を指定し、第二引数に出力対象とするHTML要素を指定します。
React.DOMというクラスのh1メソッドで、Hello Casley!という値を囲ったh1タグを生成していきます。
このh1のことをコンビニエンスラッパーと呼び、HTMLタグの分だけメソッドが用意されています。
コンビニエンスラッパーの引数には、HTML要素に適用する属性を連想配列で指定できるのですが、
特に指定しない場合は、nullでOKです。

第二引数で、対象とするHTML要素を取得しています。
今回はidがmainのものに対して、h1タグを付けるのでidがmainの要素を取得します。

上記では、ReactDOM.renderの第一引数にコンポーネントを直接定義しましたが、
予めコンポーネントを定義し、それを利用した形を見てみましょう。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>HelloWorld</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
  </head>
  <body>
    <div id="main"></div>
    <script>
      var MyComponent = React.createClass({
        render: function(){
          return React.DOM.h1(null,'Hello Casley!');
        }
      });
      // コンポーネントの利用
      ReactDOM.render(
        React.createElement(MyComponent),document.getElementById('main')
      );
    </script>
  </body>
</html>

ソース抜粋

<script>
  var MyComponent = React.createClass({ // ①コンポーネント生成します宣言
    render: function(){ // ②コンポーネントの中身定義します
      return React.DOM.h1(null,'Hello Casley!');
    }
  });
  // コンポーネントの利用
  ReactDOM.render( // ③ 定義したコンポーネントを呼び出します
    React.createElement(MyComponent),document.getElementById('main')
  );
</script>

①ではReact.createClassはコンポーネントを生成するためのメソッドで、
引数にはコンポーネントのメソッド定義を連想配列にした値を指定します。
②ではコンポーネントに対してrenderメソッドを定義して、
コンビニエンスラッパーで生成したh1タグを返却するように記述します。
③ではReact.createElementというメソッドで、定義済みのコンポーネントを呼び出しています。

React_image1

プロパティとステートについて

コンポーネントには、プロパティ(props)とステート(state)という概念があります。

プロパティとは、コンポーネントに与える属性のようなもので処理の内部で変数のように自由にアクセスできますが、
コンポーネント自身が値を変更することはできません。

ステートはコンポーネント内部で扱う変数のようなもので外部からアクセスすることはできません。

プロパティについて

プロパティを利用したコードを確認してみましょう。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>HelloWorld</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
  </head>
  <body>
    <div id="main"></div>
    <script>
      // コンポーネントの定義
      var MyComponent = React.createClass({
        render: function(){
          // h1タグにプロパティの値を表示する
          return React.DOM.h1(null,this.props.val);
        }
      });
      // コンポーネントの利用
      ReactDOM.render(
        // プロパティ「val」に'Hello Casley!'をセットする
        React.createElement(MyComponent, {val:'Hello Casley!'}),
        document.getElementById('main')
      );
    </script>
  </body>
</html>

ソース抜粋

// コンポーネントの定義
var MyComponent = React.createClass({
  render: function(){
    // h1タグにプロパティの値を表示する
    return React.DOM.h1(null,this.props.val);
  }
});
// コンポーネントの利用
ReactDOM.render(
  // プロパティ「val」に'Hello Casley!'をセットする
  React.createElement(MyComponent, {val:'Hello Casley!'}),
  document.getElementById('main')
);

React_image2

ステートについて

ステートは、コンポーネントの状態保持に使われるものです。
以下に、Reactで文字数をカウントするJSを記載してみます。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>HelloWorld</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
  </head>
  <body>
    <div id="main"></div>
    <script>
      // コンポーネントの定義
      var MyComponent = React.createClass({ // ①コンポーネント作成
        getInitialState: function() { // ② ステートの初期化
          return { count: 0}
        },
        render: function(){  // ③コンポーネントの中身定義
          return React.DOM.div(
            null,
            React.DOM.input({
              type: 'text',
              onChange: this.doChange
            }),
            React.DOM.span(null, this.state.count)
          );
        },
        doChange: function(e) { // ④changeイベント時の挙動記載
          this.setState({count: e.target.value.length});
        }
      });

      ReactDOM.render(
        // コンポーネント呼び出し
        React.createElement(MyComponent, null),
        document.getElementById('main')
      );
    </script>
  </body>
</html>

ソース抜粋

// コンポーネントの定義
var MyComponent = React.createClass({ // ①コンポーネント作成
  getInitialState: function() { // ② ステートの初期化
    return { count: 0}
  },
  render: function(){ // ③コンポーネントの中身定義
    return React.DOM.div(
      null,
      React.DOM.input({
        type: 'text',
        onChange: this.doChange
      }),
      React.DOM.span(null, this.state.count)
    );
 },
 doChange: function(e) { // ④changeイベント時の挙動記載
   this.setState({count: e.target.value.length});
 }
});

③について、少し補足します。

③ではdivタグの中に、inputタグとspanタグを記載しています。

一般的には複数の要素を作ってつくることがほとんどだと思いますが、
Reactのrender関数では、ルート要素を一つしか返却してはいけない決まりになっているため
ルート要素であるdivを返すことになります。

この書き方をすることがほとんどだと思いますので、この書き方を覚えておくといいでしょう。

React_image3

<カウンター動作>
counter_sample

仮想DOMについて

仮想DOMは、コンポーネントと並んで大事な概念です。
Webページのレンダリングというのは、Webブラウザ自身の役割となります。

また、レンダリングというのはページ上の要素が多ければ多いほど処理時間が長くなるものです。
そこで、Reactでは以下の仕組みをとりました。

  • 自身の配下に本物のDOMとは別の仮想的なDOMを構築する
  • 細かな更新は仮想DOMに対して反映しておく
  • DOMと仮想DOMの差分を割り出す
  • 差分のみをDOMに反映することにより、更新処理を最小限にとどめる

React_image4

上記の仕組みはReactが裏側でやっていることで、最初の頃は意識することはないですが、
どのようなことをやっているのか、ということをイメージとして覚えておくといいと思います。

JSXの紹介

JSXとは、Javascript XMLの略になります。
ReactとJSXは、切り離せないものになると思います。
サンプルとして、上記の文字数をカウントするJSをJSXを利用して書き換えると下記のようになります。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>HelloWorld</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js"></script>
    <script src ="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.js"></script> // JSXを利用するときに必要なJS
  </head>
  <body>
    <div id="main"></div>
    <script type="text/babel"> // text/babelを指定する
      // コンポーネントの定義
      var MyComponent = React.createClass({
        getInitialState: function() {
          return { count: 0}
        },
        render: function(){
          return (
            <div>
              <input type ='text' onChange={this.doChange}></input>
              <span>{this.state.count}</span>
            </div>
          );
        },
        doChange: function(e) {
          this.setState({count: e.target.value.length});
        }
      });

      ReactDOM.render(
        // コンポーネント呼び出し
        React.createElement(MyComponent, null),
        document.getElementById('main')
      );
    </script>
  </body>
</html>

2つのコードの印象の違いはどうでしょうか。

JSXを使わないコードだと、いまいち意味が理解しづらかったかり、複雑な印象を受けたと思います。
しかし、JSXを使うとHTMLの要素を利用して書くことができるので、
何をしているのか、直感的に理解しやすいのではないでしょうか。

JSXとHTMLの違い

上記で述べたとおり、JSXはJavascript XMLです。HTMLとは異なる部分があります。

■HTMLでは必要ない閉じタグもJSXでは必要
上記のinputタグは閉じタグが必要ない要素だが、inputの閉じタグを消して再描画するとエラーとなる

■イベントハンドラはキャメルケースで書く必要がある
HTMLではイベントハンドラはすべて小文字で書くが、JSXではonChangeとキャメルケースで書く必要がある

■属性の書き方
・class属性とfor属性はJavascriptの予約語としてあるためclassはclassName , forはhtmlForと表現する
・スタイル属性は二重の波かっこで囲む
・HTML上でハイフンで連結するスタイル(font-style , background-colorなど)はキャメルケースで表現する

以下属性の書き方のサンプルになります。

<span className='count' style={{fontStyle :'italic', color:'red'}}>{this.state.count}</span>

以上の違いがありますので、エラーなどになったときには、この違いがあることを意識しておくとよいかもしれません。

まとめ

いかがでしたでしょうか。
今回は、Reactの基礎の部分を記載させていただきました。

Reactを業務で使うとなると、Node.jsやReduxなどを組み合わせて使用することになるかと思います。
そこの部分も掘り下げて、わかりやすく今後お伝えしていければと思います。

Reactでできることや得意なこと、私自身まだまだ勉強途中ですがこのブログを通して
Reactへの興味をもつきっかけ、学習のきっかけになればと思います。

ここまでお読みいただき、ありがとうございました。