「Reactビギナーズガイド」でReactを勉強する。

同書の書評は[「Reactビギナーズガイド」を読みました。」](http://takkiii.hatenablog.com/entry/2017/03/17/235421)という同タイトルのブログを書いているので興味のある方はご覧ください。

## 今回の目標
今回の目標は「Reactビギナーズガイド」のサンプルアプリケーションをRailsに乗せて作る。
(React歴1.5ヶ月くらいなのでどうか温かい目で読んで頂けると...)

## 1. 開発準備

### 1-1. Railsアプリケーションの作成
バージョン: Ruby 2.4.0, Rails 5.0.1

```
rails new アプリケーション名
```

### 1-2. posts_controllerの作成
同書で作る「WhinePad」というアプリケーションは「ワインについてのメモや評価を記録できるアプリケーション」とのことですが、もう少し庶民的なアプリケーションにしたいので「BookPad」という「書籍についてのメモや評価を記録できるアプリケーション」に路線変更をしたいと思います。

ということで、Rails側では「books」という命名でコントローラを作成したいと思います。

```
rails g controller books index
```

とりあえず`index`アクションを作成しておきます。

### 1-3. package.jsonの作成
ReactやReact開発をする上で入れておきたいJavaScriptライブラリはnpmで管理したいのでpackage.jsonを用意します。

```
npm install --save ライブラリ名
```

とすることでインストールしたライブラリをpackage.jsonに書き込んでくれます。
こうしておけばpackege.jsonに書き忘れることはないし、アルファベット順で書き込んでくれpackage.jsonの見通しが良くなるため僕は大抵`--save`オプションをつけるようにしています。

というわけで、まずは最低限必要な以下のライブラリをインストールしておきます。

* React
* ReactDOM

```
npm install --save react react-dom
```
`node_modules`というディレクトリに大量のライブラリがインストールされるので、`.gitignore`とかに指定しておきましょう。

### 1-4. React用のディレクトリを作成する
[webpackを使った Rails上でのReact開発](http://techlife.cookpad.com/entry/2016/07/27/101015)というクックパッドの開発者ブログを読むと`app`配下に`client`というディレクトリを作成しています。個人的には`client`よりも`frontend`とかの方が直感的だと思ったので`frontend`にしています。

## 2. HelloWorld

### 2-1. books.jsの作成
ここまでで準備は整ったので、Reactのコードを書き、HelloWorldを表示していきたいと思います。
Reactではコードのまとまりを**コンポーネント**という概念として表現しているので`app/frontend`ディレクトリに`books.js`というファイルを作成します。

### 2-2. Postsコンポーネントの作成
今回はECMAScriptを使ってJavaScriptを記述していきます。

```
import React from 'react'

class Books extends React.Component {
  render() {
    return (
      <h1>HelloWorld</h1>
    )
  }
}
```

ECMAScriptではクラスを定義できるので`React.Component`を継承した`Books`クラスを作成します。
コンポーネントの作成においては様々な書き方があるのでざっと見てみたい方は[Stateless な React Component の記法をまとめてみた](http://qiita.com/kotaroito/items/e36ebac185b6b1d8538d)などを参照すると良いかと思われます。

また作成したコンポーネント内では`render()`メソッドが記述されていますが、こちらはマストで記述する必要があり、逆に`render()`メソッドさえ記述されていれば最低限のReactコンポーネントとして成立します。このあたりについては「**React コンポーネント ライフサイクル**」などで検索すると概要が掴めるかと思います。

### 2-3. コンポーネントの描画
```
import React from 'react'
import ReactDOM from 'react-dom' // 追記

class Books extends React.Component {
  render() {
    return (
      <h1>HelloWorld</h1>
    )
  }
}

// 以下を追記
ReactDOM.render(
  React.createElement(Books),
  document.getElementById("books")
)
```

`React.createElement(Books)`という部分でPostsコンポーネントを元にDOM要素を作成し、`document.getElementById("books")`という部分でpostsというid属性を持つHTMLにDOM要素を描画しています。

コンポーネントが描画される`app/views/index.html.erb`には`books`というid属性を持つHTMLを記述していきます。

```
<div id='books'></div>
```

### 2-4. Babelのインストール
さて、描画するためのコードも書いたら後はJavaScriptをRailsに読み込ませるだけです。
しかしES6はまだ各ブラウザで対応されていなかったり、一部対応という状況なので現在のブラウザに対応する形に変換(トランスパイル)する必要があります。

同書ではトランスパイラとして「**Babel**」を使用しているのでそちらをインストールしていきます。ES6やBabelについては[ES6の概要と、最新ブラウザに対応させる「Babel」の使い方](https://liginc.co.jp/260178)などが参考になるかと思います。

```
npm install --global babel-cli
```

`--global`オプションでグローバルにインストールすることで、システムのどこからでもbabelを使用できます。

### 2-5. JavaScriptのトランスパイル
```
babel --presets react,es2015 app/frontend -d app/frontend/build
```

最もシンプルなbabelのコマンドは`babel 変換したいファイル名 --out-file 変換後のファイル名`という形になりますが、今回は`app/frontend`ディレクトリにあるReactとes2015(ES6)のコードを丸ごと`app/frontend/build`ディレクトリにトランスパイルしています。

実際にトランスパイルしたファイルを開いてみると、15行程度で記述されていたReactのコードが44行程度のJavaScriptに変換されています。

### 2-6. Browserify
ES6のコードを変換してブラウザに対応させることができました。
あとはほぼRailsに読み込ませるだけと言っても過言ではないのですが、最後に問題となるのが依存関係です。

これまで書いたコードでは`React.Component`を継承するためにファイル先頭で`import React from 'react'`というコードがあります。(同様にReactDOMも)トランスパイルしたファイルをRailsで読み込んでも、ここの`import`、つまり依存先が読み込めないのでコンポーネントの描画がうまくいきません。

そこで必要となるのが**Browserify**というライブラリです。
Browserifyはファイル内にrequire()という関数を見つけると、requireに指定してあるファイルを探し、依存関係を解決してくれます。
参考資料: [Browserifyによる依存関係の解決](https://app.codegrid.net/entry/browserify-1)

```
$ npm install --global browserify
$ browserify app/frontend/build/books.js -o public/assets/javascripts/bundle.js
```

babelによって`import`構文が`require()`関数へと変換されているので、browserifyを実行すると依存関係を解決した状態で、bundle.jsというファイルへ書き出してくれます。

先ほどのトランスパイル済みのファイルは44行程度のJavaScriptだったのですが、browserifyで依存関係を解決した1つのファイルにまとめると数千行にも及ぶJavaScriptとなっていることが分かります。

### 2-7. Railsで読み込む
同書ではRailsについて一切触れられていないのでこの辺りのベストプラクティスがよく分かっていないのですが、とりあえず今回は`public/assets/javascripts`ディレクトリにbundle.jsを作成したので、これを読み込みます。

`views/layouts/application.html.erb`の`</body>`の上に以下の1行を追加します。

```
<%= javascript_include_tag '/assets/javascripts/bundle.js' %>
```

`<head></head>`内で読み込むと、`<div id='books'></div>`の読み込みよりも先にjsが読まれ、`Target container is not a DOM element.`というエラーが発生してしまいます。(解決策ご存知の方がいればご教授お願いします...)

さて、この時点で`rails s`を実行すると`localhost:3000/books/index`で**HelloWorld**と表示されるはずです。

![image](https://qiita-image-store.s3.amazonaws.com/0/59672/8065011f-139d-9fad-3380-0d26952e1fac.png)


## 今後の実装
とりあえずHelloWorldを表示させることができたら、React開発の基盤を準備することができたとみて問題ないでしょう。今後は「Reactビギナーズガイド」に沿ってコンポーネントを作成したり、データを取り扱った開発について投稿できればと思います。

Amazonでも買えます: [Reactビギナーズガイド ―コンポーネントベースのフロントエンド開発入門](http://amzn.to/2ncMEnv)