RailsのWebpackでReactに挑戦 (3) リスト表示
続きです。・・・ずいぶん時間が経過してますが・・・。
で、リスト表示ってどうすんの?
さて・・すっかり放置しておりましたが、前回エラーとなっていた部分について、考えてみます。
どうやら、複数のタグをコンポーネントとする場合には、全体を外包する要素が必要な様子。
つまり、これは駄目。
const Hoge = () => ( <li>hoge</li> <li>hoge</li> <li>hoge</li> )
で、これはOK。
const Hoge = () => ( <ul> <li>hoge</li> <li>hoge</li> <li>hoge</li> </ul> )
という事で、結局これなら動くぞ・・というのがこちら。
index.html.erb
ontpages#index</h1> <p>Find me in app/views/frontpages/index.html.erb</p> <section id="section"> <h2>sample_list</h2> </section> <%= javascript_pack_tag 'list_test' %>
list_test.jsx
import React from 'react' import ReactDOM from 'react-dom' const Hoge = () => ( <ul> <li>hoge</li> <li>hoge</li> <li>hoge</li> </ul> ) var target = document.getElementById("section").appendChild(document.createElement("ul")); document.addEventListener('DOMContentLoaded', () => { ReactDOM.render( <Hoge/>, target, ) })
無事表示です。
ただ、これはかなりイケてなくて、レンダリングされる構造は、
<ul> <ul> <li>hoge</li> <li>hoge</li> <li>hoge</li> </ul> </ul>
このようになってしまいます。
おかしさ演出で ul
にしていますが、これは div
だとしても当然狙った構造にはならないです。
やはりコレにしたい。
<ul> <li>hoge</li> <li>hoge</li> <li>hoge</li> </ul>
ただ、どうやらReactの render
の動きとしては、指定した要素の配下にコンポーネントを差し込む為、仕方がないようです。
要は、一旦差し込んでから、別途コンポーネントの親要素のみを削除すると・・・。
なんと非効率的な・・・と思ったらありました。解決方法。
<React.Fragment>
というタグ、または <>
で囲んでしまえ・・・ということで、やってみました。
結果・・。
const Hoge = () => ( <React.Feagment> <li>hoge</li> <li>hoge</li> <li>hoge</li> </React.Feagment> )
<React.Feagment>
の場合、
<>
の場合、
・・・・・何これ死にたい。
暫くハマった後で気がついたのですが、
このあたりを眺めていると・・・
あ・・・バージョン・・・。と思い立って調べてみましたが、
07:05:react_test (master *+)$ npm outdated Package Current Wanted Latest Location @rails/webpacker 3.0.2 3.5.3 3.5.3 react_test coffeescript 1.12.7 1.12.7 2.3.1 react_test prop-types 15.6.0 15.6.1 15.6.1 react_test react 16.1.1 16.4.0 16.4.0 react_test react-dom 16.1.1 16.4.0 16.4.0 react_test webpack-dev-server 2.9.4 2.11.2 3.1.4 react_test
やはり取り残されていました・・。そういえば、以前このサンプルを作った時からだいぶ経っていました。 しかし、アプデは何か起こりそうなのと、趣旨が変わってしまいそうなので、一旦アプリを作り直します。
package.json
{ "name": "react_test", "private": true, "dependencies": { "@rails/webpacker": "3.5", "babel-preset-react": "^6.24.1", "prop-types": "^15.6.1", "react": "^16.4.0", "react-dom": "^16.4.0" }, "devDependencies": { "webpack-dev-server": "2.11.2" } }
ということで、今回は、こんな感じになりました。
では、いざ表示を・・・
おおお・・・来ました!!!
ちなみに、
const Hoge = () => ( <> <li>hoge</li> <li>hoge</li> <li>hoge</li> </> )
↑これは構文エラーのままでした。どうやら、きちんと書かねば駄目っぽいです。
ともあれ、今回はここまでにします。
次はいよいよ動的にリスト表示する段階に行きたいなぁ・・・(ハマらなければ・・・)
RailsのWebpackでReactに挑戦 (2) コンポーネント
続きです。
前回は、とりあえず起動に成功したので、何を変えたらどうなるのか・・・的な考察をやってみたいと思います。
さて、コンポーネントとはなんぞ?
まずは、Reactを構成するコンポーネントについて考えてみます。
まずは、余分な情報を除きたかったので、サンプルをコピーしつつ、最初の定義らしいものを表示させるようにしてみます。
import React from 'react' import ReactDOM from 'react-dom' import PropTypes from 'prop-types' const Hello = props => ( <div>Hello {props.name}!</div> ) const Hoge = () => ( <li>hoge</li> ) Hello.defaultProps = { name: 'David' } Hello.propTypes = { name: PropTypes.string } document.addEventListener('DOMContentLoaded', () => { ReactDOM.render( <Hello name="React" />, document.body.appendChild(document.createElement('div')), ) }) document.addEventListener('DOMContentLoaded', () => { ReactDOM.render( <Hoge/>, document.body.appendChild(document.createElement('ul')), ) })
このようにサンプルを書き換えてみました。
追記箇所としては、
const Hoge = () => ( <li>hoge</li> ) document.addEventListener('DOMContentLoaded', () => { ReactDOM.render( <Hoge/>, document.body.appendChild(document.createElement('ul')), ) })
この部分となります。
まずは最初のステップですので、ステータスやバリデーションらしきモノを排除してプレーンな定義としています。
しらべてみると、ここの
const Hoge = () => ( <li>hoge</li> )
が、コンポーネントとなり、やっているのは、アロー関数を使った定義のようです。
よく書籍なんかで出ている React.createClass
の記法(すでに非推奨)を今風に書き換えたものらしい。
個人的には、
const Hoge = () => { return( <li>hoge</li> ) }
このぐらいでも良いけど、(実際動く)が、折角新しい事を覚えるので、シンプルに覚えたいですね。
さて、結果ですが・・・
無事にリスト表示されています。
デベロッパーツールでもこの通り。
しかし、ソース表示だと、
ファイル呼んでるだけ・・・まぁ、そらそうですよねw
ちなみにですが、
const Hoge = (props) => ( <li>hoge</li> )
このようにやってもエラー出ませんし、
const Hoge = (props) => ( <li>hoge{props.name}</li> )
こうしてもエラーになりません。
render側で、
document.addEventListener('DOMContentLoaded', () => { ReactDOM.render( <Hoge name="hoge" />, document.body.appendChild(document.createElement('ul')), ) })
このように、 <Hoge/>,
に name
を付け加えると値が反映されます。
狙い通りきちんと、fugafuga したようです。
さて、ここで疑問なのですが、
const Hoge = props => ( <li>hoge{props.fuga}</li> ) document.addEventListener('DOMContentLoaded', () => { ReactDOM.render( <Hoge huga="hoge" />, document.body.appendChild(document.createElement('ul')), ) })
このように、 name
を fuga
と適当に変えてみるとどうなるのか試したらどうなるか。
はい。今度は残念な結果となりました。
これはアローの引数が、何か固定のプロパティ名を複数?持っているという話になりますね。
詳しく調べるのは後回しとしまして・・・次に、 props
は通常何でも良いと考えていたのですが、プロパテイをすでに持っているとなるとちょっと怖いので、念のため試しておきましょう。
const Hoge = fugafuga => ( <li>hoge{fugafuga.name}</li> ) document.addEventListener('DOMContentLoaded', () => { ReactDOM.render( <Hoge name="hoge" />, document.body.appendChild(document.createElement('ul')), ) })
このように変更すると・・・
あ・・・これは大丈夫のようです。
ということはやはり、ただのブロック変数という事ですね。
しかし、他に用途がないのであれが、ネーミング的には props
でしっくり来るのでそのままで良い気がしますね。
という事で、最低限書いておくと良い記述としては、
const Hoge = 変数名 => ( <div>HTMLが普通に書ける{ ブロックで変数のプロパティが展開出来る }</div> )
こんな感じかと思われます。
さて、ここで気を良くして、「折角リストなんだから複数入れてみよう。」という話になりますよね。
試してみます。
const Hoge = props => ( <li>hoge</li> <li>hoge</li> <li>hoge</li> )
はい・・ではどうなるか・・。
結果:惨敗
駄目みたいですね。というかエラー画面が無駄にカッコいいんですけど・・・。
エラー画面で折れたので、今日はここまでです。
次回は、リスト表示などのくりかえし要素を作る方法を実験する予定です。
RailsのWebpackでReactに挑戦 (1)
タイトルそのままなのですが、前回作った環境 を元にReactのチュートリアルをやってみたいと思います。
が、今回はただの準備編です。まだ内容には触れずに導入時に作られたサンプルを確認して概要を掴んでみます。
今回の実行環境です。
$ ruby -v ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-darwin15] $ bundle exec rails -v Rails 5.1.4 $ node -v v8.7.0
実装します。
まずは、トップページのコントローラーを作ります。
react_test $ bundle exec rails g controller frontpages index Running via Spring preloader in process 4765 create app/controllers/frontpages_controller.rb route get 'frontpages/index' invoke erb create app/views/frontpages create app/views/frontpages/index.html.erb invoke test_unit create test/controllers/frontpages_controller_test.rb invoke helper create app/helpers/frontpages_helper.rb invoke test_unit invoke assets invoke coffee create app/assets/javascripts/frontpages.coffee invoke scss create app/assets/stylesheets/frontpages.scss
トップページを作ります。
routes.rb
Rails.application.routes.draw do root 'frontpages#index' end
Railsでインストールした時に作られたサンプルを確認してみましょう。
app/javascript/packs/hello_react.jsx (それにしても階層にすっごい違和感w)
// Run this example by adding <%= javascript_pack_tag 'hello_react' %> to the head of your layout file, // like app/views/layouts/application.html.erb. All it does is render <div>Hello React</div> at the bottom // of the page. import React from 'react' import ReactDOM from 'react-dom' import PropTypes from 'prop-types' const Hello = props => ( <div>Hello {props.name}!</div> ) Hello.defaultProps = { name: 'David' } Hello.propTypes = { name: PropTypes.string } document.addEventListener('DOMContentLoaded', () => { ReactDOM.render( <Hello name="React" />, document.body.appendChild(document.createElement('div')), ) })
むぅ・・・なんだコレ・・・。
JSもままならぬ身としてはキツイサンプルです。
import React from 'react' import ReactDOM from 'react-dom' import PropTypes from 'prop-types'
これはライブラリを呼んでいるっぽい。どうやらライブラリ自体はローカルにインストールされていますね。
それぞれ・・・
node_modules/react/index.js node_modules/react-dom/index.js node_modules/prop-types/index.js
ここにいるようです。 そして・・・
const Hello = props => ( <div>Hello {props.name}!</div> )
これは・・・アロー関数みたいなのだけれども・・・中身にHTMLが・・・?? そして、引数付きメソッドのような感じ??
でもconst なので、定数ですよね・・。引数付き定数??
おまけに、次の
Hello.defaultProps = { name: 'David' } Hello.propTypes = { name: PropTypes.string }
に至ってはだいぶ難解ですが、どうもこちらはバリデーションか何かっぽいですね。 これは要実験です。
私のようなボンクラがこれ以上考えても仕方ないので、とりあえず動かしてみましょう。
ともかくサンプルを呼び出す記述が書いてあったので言うとおりに・・・。
app/views/frontpages/index.html.erb
<h1>Frontpages#index</h1> <p>Find me in app/views/frontpages/index.html.erb</p> <%= javascript_pack_tag 'hello_react' %>
と、 <%= javascript_pack_tag 'hello_react' %>
を追記してみます。
起動します。
1つ目のターミナルではRailsを
bundle exec rails s
2つ目のターミナルでは、webpackを動かします。
./bin/webpack-dev-server
トップページ、localhost:3000に接続すると・・・
よし・・・ここまで壮大な手間をかけてようやくHelloWorld的なやつができました。
ここまでやって今更なのですが、ちょっとカッコよくreact言ってみたかっただけなのに何なの?この苦行・・・。
そして起動だけで駄文が長くなったので、サンプルの実験は一旦切る事を決意w
Rails で react を動かす
Rails で react を動かしてみようと思った話
reactとか正直ミリも知らないのに試してみた。
Rails5.1から導入されたwebpackを使ってみた事から始まり、どうせならReactを試してみよう・・・となってしまった流れ。
前提
- Node.jsがインストールされている (試した環境では v6.11.4)
- Railsが動かせる環境がある (試した環境では ruby -v 2.4.0)
- Macローカル環境でbrewが使える (環境依存のものは読み替えの必要あり)
適当にプロジェクトを作る
$ mkdir react_test $ cd react_test $ bundle init
webpackを使いたいので、 Rails 5.1系の最新版の記述を、Gemfileに追記
Gemfile
gem 'rails', '~>5.1.0'
プロジェクト内、vendor/bundle配下にgemを展開
$ bundle install --path vendor/bundle
確認
$ yarn --version
yarnが入っていない場合はインストールする
$ brew install yarn
プロジェクトフォルダにnewする
$ bundle exec rails new . --webpack=react
何かで手順が狂った場合はwebpacker単独でインストールの続行
$ bundle exec rails webpacker:install:react
webpack用のポートを書き換え(8080番に)
別途サーバーを起動する必要があるそうな。
config/webpacker.yml
# Reference: https://webpack.js.org/configuration/dev-server/ dev_server: https: false host: localhost port: 8080 public: localhost:8080 hmr: false # Inline should be set to true if using HMR inline: true overlay: true disable_host_check: true use_local_ip: false
起動
$ bundle exec rails s $ ./bin/webpack-dev-server
以下は続きの小ネタ
サンプルとして設置されているjsxを呼び出す
(ここまでは試しておきたい)
$ bundle exec rails g controller toppages index
config/routes.rb
root 'toppages#index'
app/views/toppages/index.html.erb
<%= javascript_pack_tag 'hello_react' %>
Material-UIを使う準備をする
(使うとは言ってない)
$ yarn add redux $ yarn add react-redux $ yarn add redux-devtools --dev $ yarn add material-ui $ yarn add react-tap-event-plugin
起動を楽にする
(ログが混濁するので、使わなかった)
gem 'forman'
gemを追加後カレント以下にProcfileを作成
Procfile
rails: bundle exec rails s -p 3000 webpack: bin/webpack-dev-server
$ foreman start
heroku で poltergeist 動かしたかったので
Phantom.js の開発が止まってしまった・・・。
とは、関係なくちょいとPhantom.jsを使ってHerokuで poltergeist & capybara を動かしたかったので、
Heroku で Phantom.jsとRailsを共存させた環境を作る状況を調べてみました。
buildpackを入れ直す
$ heroku buildpacks:clear $ heroku buildpacks:add https://github.com/stomita/heroku-buildpack-phantomjs $ heroku buildpacks:add heroku/ruby
確認
$ heroku buildpacks
最後に heroku/ruby
が来ていればOK(今回は2個中の2個目)
Buildpack added. Next release on APP-NAME will use: 1. https://github.com/stomita/heroku-buildpack-phantomjs.git 2. heroku/ruby Run git push heroku master to create a new release using these buildpacks.
Herokuがどんどん便利になっているのですが、情報が変わるのが早くて良くハマります。
参考url
https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app
http://logic.moo.jp/data/archives/1060.html
はじめました
主に、書きなぐりや備忘録程度で Ruby on Rails に関して書いていこうと思います。
内容は未定です。
テンプレートエンジンは使わない
なるべく解説付き
なるべく頑張る
のスタイルでゆるーく書いていければと思っております。