* react-rails+redux インストール (Node.js無し版) [#sf2c29df]
#setlinebreak(on)
プロジェクト配下に node.js モジュールを入れずに react-rails + redux が動作可能な環境を作る。
とりあえず react-rails-redux-sample(※) を node.js モジュール無しで動かせるようにしたものを作成する。
※ https://github.com/suzan2go/react-rails-redux-sample
&br;
#contents
** railsプロジェクト作成 [#rabda7ae]
#myterm2(){{
rails new react-rails-redux
}}
** Gemfile追記 [#kc578374]
#myterm2(){{
gem 'react-rails'
}}
** bundle install [#wcb24c1a]
#myterm2(){{
bundle install --path vendor/bundle
}}
** react-railsセットアップ [#x78dea73]
#myterm2(){{
rails g react:install
Expected string default value for '--jbuilder'; got true (boolean)
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
}}
** 設定ファイル編集 [#y75526af]
config/environments/development.rb
#mycode2(){{
MyApp::Application.configure do
config.react.variant = :development # 追記
config.react.addons = true # 追記
config.react.camelize_props = true # 追記
end
}}
onfig/environments/production.rb
#mycode2(){{
MyApp::Application.configure do
config.react.variant = :production
end
}}
** ルーティング追加 [#jac7e880]
routes.rb
#mycode2(){{
Rails.application.routes.draw do
root to: 'welcome#index'
end
}}
** コントローラ作成 [#mbbf3383]
app/controllers/welcome_controller.rb
#mycode2(){{
class WelcomeController < ApplicationController
def index
end
end
}}
** ビュー作成 [#j886266f]
app/views/welcome/index.html.erb
#myhtml2(){{
<h1>Welcome#index</h1>
<%= react_component('Root', {counter: 10}, {prerender: true} ) %>
}}
** redux.js のダウンロード [#ua9111a5]
https://cdnjs.com/ から 以下をダウンロード
#myterm2(){{
cd vendor/assets/javascripts/
wget https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js
wget https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.2/react-redux.min.js
wget https://cdnjs.cloudflare.com/ajax/libs/redux-thunk/2.1.0/redux-thunk.min.js
}}
** application.js の編集 [#k88716be]
app/assets/javascripts/application.js
#mycode2(){{
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require react
//= require react_ujs
//= require redux.min // 追記
//= require react-redux.min // 追記
//= require redux-thunk.min // 追記
//= require components
//= require_tree .
}}
** js作成 [#ec439db7]
app/assets/javascripts/components/welcome/index.js.jsx
#myhtml2(){{
/****************************************************************
* react-rails-redux-sample の components 配下の js をサーバサイドjsを使用しない形に変換したもの。
* ※https://github.com/suzan2go/react-rails-redux-sample
****************************************************************/
//---------------------------------------------------------
// components/actions/counter.js
//---------------------------------------------------------
var INCREMENT_COUNTER = 'INCREMENT_COUNTER';
var DECREMENT_COUNTER = 'DECREMENT_COUNTER';
var SET_COUNTER = 'SET_COUNTER';
function setCounter(counter) {
return {
type: SET_COUNTER,
counter: counter
};
}
function increment() {
return {
type: INCREMENT_COUNTER
};
}
function decrement() {
return {
type: DECREMENT_COUNTER
};
}
function incrementIfOdd() {
return (dispatch, getState) => {
const { counter } = getState();
if (counter % 2 === 0) {
return;
}
dispatch(increment());
};
}
function incrementAsync(delay = 1000) {
return dispatch => {
setTimeout(() => {
dispatch(increment());
}, delay);
};
}
var CounterActions = {
setCounter: setCounter
,increment: increment
,decrement: decrement
,incrementIfOdd: incrementIfOdd
,incrementAsync: incrementAsync
};
//---------------------------------------------------------
// components/components/Counter.js
//---------------------------------------------------------
class Counter extends React.Component {
render() {
const { increment, incrementIfOdd, incrementAsync, decrement, counter } = this.props;
return (
<p>
Clicked: {counter} times
{' '}
<button onClick={increment}>+</button>
{' '}
<button onClick={decrement}>-</button>
{' '}
<button onClick={incrementIfOdd}>Increment if odd</button>
{' '}
<button onClick={() => incrementAsync()}>Increment async</button>
</p>
);
}
}
Counter.propTypes = {
increment: React.PropTypes.func.isRequired,
incrementIfOdd: React.PropTypes.func.isRequired,
incrementAsync: React.PropTypes.func.isRequired,
decrement: React.PropTypes.func.isRequired,
counter: React.PropTypes.number.isRequired
};
//---------------------------------------------------------
// components/containers/CounterApp.js
//---------------------------------------------------------
function mapStateToProps(state) {
return {
counter: state.counter
}
}
function mapDispatchToProps(dispatch) {
return Redux.bindActionCreators(CounterActions, dispatch);
}
var CounterApp = ReactRedux.connect(mapStateToProps, mapDispatchToProps)(Counter);
//---------------------------------------------------------
// reducers/counter.js
//---------------------------------------------------------
function counter(state = 0, action) {
switch (action.type) {
case INCREMENT_COUNTER:
return state + 1;
case DECREMENT_COUNTER:
return state - 1;
case SET_COUNTER:
return action.counter;
default:
return state;
}
}
//---------------------------------------------------------
// reducers/counter.js
//---------------------------------------------------------
var rootReducer = Redux.combineReducers({
counter
});
//---------------------------------------------------------
// components/store/configureStore.js
//---------------------------------------------------------
var createStoreWithMiddleware = Redux.applyMiddleware(ReduxThunk)(Redux.createStore);
/* このままでは動かない
function configureStore(initialState) {
return createStoreWithMiddleware(rootReducer, initialState);
}
*/
// react-rails-redux-sample の js生成結果を参考に書き直し
var createStoreWithMiddleware = (0, Redux.applyMiddleware)(ReduxThunk.default)(Redux.createStore);
function configureStore(initialState) {
return createStoreWithMiddleware(rootReducer, initialState);
}
//---------------------------------------------------------
// components/containers/Root.js
//---------------------------------------------------------
var Provider = ReactRedux.Provider;
var store = configureStore();
class Root extends React.Component {
componentWillMount() {
store.dispatch(setCounter(this.props.counter));
}
render() {
return (
<Provider store={store}>
<CounterApp />
</Provider>
);
}
}
}}