はじめに
他の方の記事を参考に自分なりに Rails + React + MySQL の環境を作ってみたので、その時のやり方をまとめました。
上からコピペするだけで動くようにまとめてみたので、はじめてだけどやってみたいという方がいらっしゃれば、試していただきたいです。
コマンド
こちらの項目で実施することは以下となります。
上から順番にターミナルで実行していただければと思います。
- やること
- rails アプリケーションの作成
- webpacker インストール
- react インストール
- MVC作成
- migration
$ rails _5.2.4.2_ new react_sample_app --webpack=react -d mysql
$ cd react_sample_app
# Webpackを有効にする
$ rails webpacker:install
# Reactを有効にする
$ rails webpacker:install:react
# sample モデルを scaffold にて作成
$ rails g scaffold sample title:string body:string
# migrate
$ rails db:create
$ rails db:migrate
※routeなどの細かい設定が面倒だと思ってscaffoldを使いましたが、scaffoldが必須というわけではありません。
View
続いては、Viewの設定をしていきます。
application.html.erb
全体へ反映させたいことをこちらに記載していきます。
- やること
-
javascript_include_tag
→javascript_pack_tag
へ変更する - view のファイル毎に読み込む javascript(React) を指定するために、
<%= yield :javascript %>
を追記
-
<!DOCTYPE html>
<html>
<head>
<title>ReactSampleApp</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<!-- javascript_include_tag を下記へ変更する -->
<!-- javascript_include_tag 'application', 'data-turbolinks-track': 'reload' -->
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= yield %>
<!-- view のファイル毎に読み込む javascript(React) を指定するために必要 -->
<%= yield :javascript %>
</body>
</html>
個別のerbファイル
ここでは例えとして、app/views/samples/index.html.erb
上に変更を加えますが、他の画面で実装していただいも何も問題ありません。
- やること
- Rails から React へ渡すデータを作成(content_tagにより)
- view のファイル毎に読み込む javascript(React) を指定する
<!-- 省略 -->
<!-- 一番下の行に以下を追記 -->
<!-- content_tag の data 属性を React へ渡す -->
<%= content_tag :div,
id: "resources-container",
data: {
q: params,
resources_path: samples_path,
}.to_json do %>
<% end %>
<!-- view のファイル毎に読み込む javascript(React) を指定することができる -->
<% content_for :javascript do %>
<%= javascript_pack_tag 'hello_react' %>
<% end %>
javascript
ここでは、コマンド入力時に作成したapp/javascript/packs/hello_react.jsx
を用いますが、個々にファイルを設定していただいて問題ありません。
- やること
- Hello コンポーネントの作成
- props を state に格納する
- state.name を更新する関数を作成する
- レンダリングする HTML要素を作成する
- Rails から読み込みたい & React からレンダリングしたい要素を指定
- 指定した要素(node)から、data を取得する
- Hello コンポーネントを呼び出し
- data を Hello コンポーネントの props として渡す
- node へ React からレンダリングする
- Hello コンポーネントの作成
import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
// Hello コンポーネントの作成
class Hello extends React.Component {
constructor(props) {
super(props)
// props を state に格納する
this.state = {
q: this.props.q || '',
resources_path: this.props.resources_path || '',
name: this.props.name || 'David'
}
}
render() {
// state.name を更新する関数を作成する
const setName = e => {
this.setState({
name: e.target.value
})
}
// レンダリングする HTML要素を作成する
return (
<div>
<div>Hello {this.state.name}!</div>
<input type="text" defaultValue={this.state.name} onChange={setName}/>
</div>
)
}
}
document.addEventListener('DOMContentLoaded', () => {
// Rails から読み込みたい & React からレンダリングしたい要素を指定する
const node = document.getElementById('resources-container')
// 指定した要素(node)から、data を取得する
const data = JSON.parse(node.getAttribute('data'))
ReactDOM.render(
// Hello コンポーネントを呼び出し
// Rails から取得した data を Hello コンポーネントの props として渡す
<Hello {...data}/>,
// node へ React からレンダリングする
node
)
})
rails s と webpacker 起動を一括して実行する方法
以下に、scripts
の部分を追記します。
すると、yarn start
をターミナル上で実行するたけで、rails s & bin/webpack-dev-server
を実行してくれます。
{
"name": "react_sample_app",
"private": true,
"dependencies": {
"@babel/preset-react": "^7.10.1",
"@rails/webpacker": "5.1.1",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
"devDependencies": {
"webpack-dev-server": "^3.11.0"
},
// 以下を追記する
"scripts": {
"start": "rails s & bin/webpack-dev-server"
}
}
$ yarn start
まとめ
いかがでしたか。
間違いなどがあれば、お手数をおかけしますがご指摘いただけると嬉しいです。
React を理解しているとスマホアプリを作れる React Native への導線が引けるかなーと思い勉強中です。
まずは、Rails と連携していけているアプリケーションを作れるようになりたいなーと思っています。