WEB+DB PRESS Vol.92にReact + Reduxのページがあってちょっと触ってみようかなと思ってから随分時間が経ってしまったけど、とりあえず環境だけできたので書いておきます。

React + Reduxだけではなく、せっかくなのでRails5でReact + Reduxな環境を作ってredux/examples/todosを動かしてみました。

参考

以下を参考にしています。

  1. http://qiita.com/suzan2go/items/24ef3320e04b8a84597f
  2. https://github.com/reactjs/redux/tree/master/examples/todos

環境

  • CentOS Linux release 7.2.1511 (Core)
  • node v0.12.15
  • Rails 5.0.0
  • react 15.2.1
  • redux 3.5.2

必要なモノをインストール

nodeとrailsをインストールします。

node.js

$ git clone https://github.com/creationix/nvm.git ~/.nvm
$ source ~/.nvm/nvm.sh
$ nvm install 0.12.15
$ nvm alias default v0.12.15
$ vi ~/.bash_profile
以下を追記
if [[ -s ~/.nvm/nvm.sh ]];
then source ~/.nvm/nvm.sh
fi
$ node -v
v0.12.15

ruby

rbenv使ったほうが楽だけどソースからインストールします。

root$ yum groupinstall "development tools"
root$ yum install zlib-devel openssl-devel gdbm-devel readline-devel ncurses-devel libffi-devel libxml2-devel libxslt-devel libcurl-devel libicu-devel libyaml-devel
root$ cd /tmp
root$ wget http://ftp.ruby-lang.org/pub/ruby/ruby-2.3.1.tar.gz
root$ tar zxvf ruby-2.3.1.tar.gz
root$ cd ruby-2.3.1
root$ ./configure
root$ make && make install
root$ ruby -v
ruby 2.3.1p112

Rails

Railsインストール。

root$ gem install rails
root$ rails -v
Rails 5.0.0

方針

react, redux, babelはnpmでインストールしたものを利用します。JavascriptのES6からES5へのトランスパイルはbrowserify-railsからBabelを呼び出して行います。
browserify-railsのコマンドラインオプションにbabelの設定をすることでトランスパイルされたJavascriptがAsset Pipelineに流れる様になります。react_railsでRailsのViewからReactComponentのHelperを使って呼び出します。

よく出来過ぎてる。

Rails側の準備

適当なプロジェクトを作っておきます。

root$ yum install sqlite-devel
$ rails new react-redux-rails-sample

rails側で利用するパッケージを追加を追加します。

Gemfile
+ # gem 'therubyracer', platforms: :ruby
+ gem 'therubyracer', platforms: :ruby
+ gem 'react-rails'
+ gem 'browserify-rails'
$ bundle install

browserifyからトランスパイラを呼び出す設定を追加。
browserifyは何って読むのでしょうか。ぶらうざりふぁい?

config/application.rb
config.browserify_rails.commandline_options = '-t babelify'

react-railsをインストールします。

$ rails g react:install
create app/assets/javascripts/components
create app/assets/javascripts/components/.gitkeep
insert app/assets/javascripts/application.js
insert app/assets/javascripts/application.js
insert app/assets/javascripts/application.js
create app/assets/javascripts/components.js

components以外のReduxで使うディレクトリは後ほど作ります。

app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require react
//= require react_ujs
//= require components
//= require_tree .

reactはnpmで入れたreactを使うので//= require reactは消し、sprocketsの機能を使ってrequireしないので//= require_tree .も消します。

Node側の準備

browserify, babel周りのパッケージをインストールします。

$ npm init
$ npm install --save-dev browserify browserify-incremental
$ npm install --save-dev babelify babel-preset-es2015 babel-preset-react

railsのアプリケーションルートに.babelrcを追加します。

{
"presets": ["es2015", "react"]
}

次にReact, Reduxのパッケージをインストールします。

$ npm install --save react react-dom react-redux redux redux-thunk

npmでインストールされたパッケージは以下の様になっています。

package.json
...
"devDependencies": {
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.11.1",
"babelify": "^7.3.0",
"browserify": "^13.0.1",
"browserify-incremental": "^3.1.1"
},
"dependencies": {
"react": "^15.2.1",
"react-dom": "^15.2.1",
"react-redux": "^4.4.5",
"redux": "^3.5.2",
"redux-thunk": "^2.1.0"
}
...

Reduxのtodosアプリを追加

Reduxのディレクトリを作ります。

$ cd app/assets/javascripts/
$ mkdir actions containers reducers

react, react-domをrequireし、3行目で読み込むtodos.jsでreact_componemtから呼べる様にする(?)。この部分が実はよくわかっていない。

components.js
window.React = require('react');
window.ReactDOM = require('react-dom');
window.Todos = require('./todos.js').default;

ここを参考にactions, components, containers, reducersのファイルをapp/assets/javascripts以下にコピペします。

index.jsは以下の様に書き換えました。

app/assets/javascripts/todos.js
import React, { Component } from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todo from './reducers'
import App from './components/App'

let store = createStore(todo)

export default class Todos extends Component {
render() {
return (
<Provider store={store}>
<App />
</Provider>
);
}
}

Viewを追加してreact_componentを使ってみます。

$ rails g controller todos index

helperからreactのコンポーネントを呼びます。

app/views/todos/index.html.erb
<%= react_component('Todos') %>

ここで、/todos/indexに接続すると以下の様に表示されることが確認できます。

サーバサイドレンダリングしたい場合は{prerender: true}を渡すとサーバサードレンダリングができます。ブラウザ側のJavascriptを無効にして再読み込みするとレンダリングされることが確認できると思います。

まとめ

browserify_railsのビルドが遅いので他の方法を探す必要がありそうです。とりあえずReact + Reduxの環境ができたので時間があるときにさわってみようかと思っています。React-Bootstrapまでやろうと思ったけど時間が無いのでまたの機会に。

おわり。