Reactサンプルを表示
次にReactのサンプルページを作成します。以下のジェネレーターコマンドでpagesコントローラーを作成します。
bin/rails g controller pages index
トップページにアクセスできるように自動生成されたルーティングを以下の通り書き換えます。
+++スクリプト+++ Rails.application.routes.draw do root to: 'pages#index' …(中略)…
レイアウトファイルの中にある、JavaScriptをインクルードするヘルパーメソッドのjavascript_include_tagを以下の通り書き換えます。
…(中略)…
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
…(中略)…
javascript_pack_tagは、前述のwebpackerというgemが提供するヘルパーメソッドです。このメソッドを使用することで、インクルードするJavaScriptをapp/assets/javascripts/ではなく、app/javascript/packs/から探すようにRailsの動作が変わります。Railsアプリを新規作成した時点で、Reactのサンプルファイルが生成されています。このサンプルファイルを確認します。
…(中略)…
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をインクルードするように以下の通り設定を追加します。
…(中略)…
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が無事に動いています。
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を指定しています。
…(中略)…
"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コードの追加
トップページのビューファイルを以下の通り修正します。
<h1>Rails 5.1サンプルアプリケーション</h1> <p>ReactベースのMaterial-UI(カード)を使う</p>
カードコンポーネントを呼び出すReactのコードを以下の通り記述します。Material-UIのカードコンポーネントとは、カード型のUIをWebブラウザ上で簡単に表現するために用意されているモジュールです。
// 著註:必要なパッケージをインクルード
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では大きくフロントエンド環境が整備されたといえます。
