SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

サンプルコードで学ぶRuby on Rails 5実践入門

Rails 5.1でReact.js連携アプリを構築してみよう

サンプルコードで学ぶRuby on Rails 5実践入門 番外編

Reactサンプルを表示

 次にReactのサンプルページを作成します。以下のジェネレーターコマンドでpagesコントローラーを作成します。

bin/rails g controller pages index

 トップページにアクセスできるように自動生成されたルーティングを以下の通り書き換えます。

config/routes.rb
+++スクリプト+++
Rails.application.routes.draw do
  root to: 'pages#index'
…(中略)…

 レイアウトファイルの中にある、JavaScriptをインクルードするヘルパーメソッドのjavascript_include_tagを以下の通り書き換えます。

app/views/layouts/application.html.erb
…(中略)…
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
…(中略)…

 javascript_pack_tagは、前述のwebpackerというgemが提供するヘルパーメソッドです。このメソッドを使用することで、インクルードするJavaScriptをapp/assets/javascripts/ではなく、app/javascript/packs/から探すようにRailsの動作が変わります。Railsアプリを新規作成した時点で、Reactのサンプルファイルが生成されています。このサンプルファイルを確認します。

app/javascript/packs/hello_react.jsx
…(中略)…
import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'

// (3):JSX形式で記述された仮想DOMを出力
const Hello = props => (
  <div>Hello {props.name}!</div>
)

// (4):Helloの引数(props)のデフォルト値を設定
Hello.defaultProps = {
  name: 'David'
}

// (5):Helloの引数(props)のデフォルト値のデータ型を設定
Hello.propTypes = {
  name: PropTypes.string
}

// (1):DOMロード後に指定したDOMを追加
document.addEventListener('DOMContentLoaded', () => {
  // (2):第1引数に指定したDOMを第2引数に指定した箇所に追加
  ReactDOM.render(
    <Hello name="React" />,
    document.body.appendChild(document.createElement('div')),
  )
})

 サンプルファイルの拡張子は、JavaScript文法を拡張したものであるjsxとなっています。ソースコードはシンプルなReactのコードです。document.addEventListenerでDOMがロードされた後、ReactDOM.renderでDOMの操作を行っています。(ソースコード(1)参照)第1引数に出力するDOMツリーを、第2引数にDOMツリーを出力する場所を指定します。(ソースコード(2)参照)第1引数のHelloはconstで定義している仮想DOMを指します。props.nameで指定元のname属性を取得することができます。(ソースコード(3)参照)Hello.defaultPropsはname属性が指定されていなかった場合のデフォルト値を(ソースコード(4)参照)、Hello.propTypesはname属性のデータ型を定義しています。(ソースコード⑤参照)

 まとめるとこのReactのコードがインクルードされると「Hello React!」というテキストがdiv要素で出力されます。なお、React.jsに関するより詳細な解説はこちらの連載を参照ください。

 このサンプルファイルhello_react.jsxをインクルードするように以下の通り設定を追加します。

app/javascript/packs/application.js
…(中略)…
console.log('Hello World from Webpacker')
require('./hello_react.jsx')

 webpackを都度ビルドするにはbin/webpackコマンドが用意されています。しかしこのコマンドはJavaScriptファイルが修正される度ごとに実行する必要があり面倒です。これを解消するため、webpackerが用意するbin/webpack-dev-serverコマンドがあります。このコマンドを実行するとJavaScript関連ファイルの修正を監視して、修正が入る都度、webpackによるビルド処理が走ります。

 以下の通りbin/webpack-dev-serverコマンドを実行します。

bin/webpack-dev-server

 実行結果の最後に「webpack: Compiled successfully.」と出力されたらwebpackによるコンパイルに成功しています。

 以下のコマンドでRailsサーバー(puma)を起動します。

bin/rails s

 起動したRailsにアクセスしてみましょう。localhost:3000にアクセスして「Hello React!」が表示されていることが確認できれば、Rails上でReactが無事に動いています。

http://localhost:3000
http://localhost:3000

ReactベースのMaterial-UIをインストールする

 Reactが無事に動いたので、今度はReactベースのMaterial-UIをインストールしてみましょう。Material-UIは、Googleが提供するMaterial Designと呼ばれるデザインガイドラインが提供しているUIパーツを、Reactコンポーネントとして提供するパッケージです。デザインにそれほど強くないサーバーサイドエンジニアでも、よりリッチで分かりやすいUIを手軽に構築できます。本記事では、Material-UIが提供するカードコンポーネントを使います。

Yarnパッケージの追加

 Yarnパッケージは、package.jsonで管理されています。Railsプロジェクト生成時に作成されたpackage.jsonに以下の通りmaterial-uiとreact-tap-event-pluginを追加します。react-tap-event-pluginはmaterial-uiが依存しているパッケージです。本記事執筆時点で最新のバージョンである0.18.0を指定しています。

package.json
…(中略)…
    "webpack-merge": "^4.1.0",
    "material-ui": "^0.18.0",
    "react-tap-event-plugin": "^2.0.1"
  },
…(中略)…

 以下のコマンドで追加したmaterial-uiパッケージをインストールします。

bin/yarn install

 実行後、yarn.lockファイルが更新されJavaScriptの依存関係が再整理されます。これはbundlerによるコマンドと同様です。package.jsonがbundlerでいうところのGemfile、yarn.lockがGemfile.lockにあたります。また、追加でインストールされたJavaScriptパッケージはnode_modulesディレクトリ配下に配置されます。node_modulesはbundlerでいうところのvendor/bundleにあたります。なお、node_modulesディレクトリ配下は.gitignoreに指定が追加されgit管理対象外となっています。

ビューファイルの修正・Reactコードの追加

 トップページのビューファイルを以下の通り修正します。

app/views/pages/index.html.erb
<h1>Rails 5.1サンプルアプリケーション</h1>
<p>ReactベースのMaterial-UI(カード)を使う</p>

 カードコンポーネントを呼び出すReactのコードを以下の通り記述します。Material-UIのカードコンポーネントとは、カード型のUIをWebブラウザ上で簡単に表現するために用意されているモジュールです。

app/javascript/packs/expandable_example.jsx
// 著註:必要なパッケージをインクルード
import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
import {Card, CardActions, CardHeader, CardText} from 'material-ui/Card'
import FlatButton from 'material-ui/FlatButton'
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme'
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import injectTapEventPlugin from 'react-tap-event-plugin'
injectTapEventPlugin()

// カードコンポーネントを定義
class CardExampleExpandable extends React.Component {
  // コンストラクタ
  constructor(props) {
    super(props)
  }

  // テーマを指定
  getChildContext() {
    return { muiTheme: getMuiTheme(baseTheme) }
  }

  // DOMをレンダリング
  render() {
    return (
      // カードコンポーネントのDOM
      <Card>
        // ヘッダー
        <CardHeader
          title="Rails 5.1サンプルアプリ開発"
          subtitle="Rails 5.1を体感する為のサンプルアプリケーションを開発する。"
          actAsExpander={true}
          showExpandableButton={true}
        />
        // アクション
        <CardActions>
          <FlatButton label="完了" />
          <FlatButton label="中止" />
        </CardActions>
        // テキスト
        <CardText expandable={true}>
          ・Rails 5.1より採用されたyarn,webpackを用いる<br/>
          ・Reactを採用しReactベースのMaterial-UIを入れてみる
        </CardText>
      </Card>
    )
  }
}

// テーマを指定
CardExampleExpandable.childContextTypes = {
  muiTheme: PropTypes.object.isRequired
}

// DOMロード後に指定したDOMを追加
document.addEventListener('DOMContentLoaded', () => {
  // CardExampleExpandableをレンダリング
  ReactDOM.render(
    <CardExampleExpandable />,
    document.body.appendChild(document.createElement('div')),
  )
})

 基本的な流れはMaterial-UIのサンプルコードをほぼ流用しているので詳細な説明は省略します。document.addEventListenerでカードのDOMツリーを呼び出す流れは先ほどのサンプルコードと同様です。

動作確認

 この時点で再度localhost:3000にアクセスし、以下の画像と同じカードのようなUIが表示されれば成功です。

アクセス初期状態(カードが閉じた状態)
アクセス初期状態(カードが閉じた状態)

 このカードの右側のマークをクリックするとカードが開きます。

カードを開いた状態
カードを開いた状態

まとめ

 Rails 5.1で採用されたYarn、webpackを使うと、簡単にRails上でReactを使うことができます。また、Material-UIを使ってよりリッチなUIを簡単に実現することができます。Rails 5.1では大きくフロントエンド環境が整備されたといえます。

参考文献

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
サンプルコードで学ぶRuby on Rails 5実践入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 竹馬 力(チクバ ツトム)

WINGSプロジェクト について> 有限会社 WINGSプロジェクト が運営する、テクニカル執筆コミュニティ(代表 ...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/10209 2017/06/12 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー