Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

同書の書評は「Reactビギナーズガイド」を読みました。」という同タイトルのブログを書いているので興味のある方はご覧ください。

今回の目標

今回の目標は「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開発というクックパッドの開発者ブログを読むと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 の記法をまとめてみたなどを参照すると良いかと思われます。

また作成したコンポーネント内では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」の使い方などが参考になるかと思います。

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による依存関係の解決

$ 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/indexHelloWorldと表示されるはずです。

image

今後の実装

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

Amazonでも買えます: Reactビギナーズガイド ―コンポーネントベースのフロントエンド開発入門

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away