Redux勝手にチュートリアル(Counter)
最近流行りのReduxをより深く理解するために、 「分かりやすい」を目指して勝手にチュートリアルを書いてみます。
自分的には結構複雑に見えたんですが、 他のフレームワークやアーキテクチャに慣れていると簡単なのでしょうか?
参考: http://qiita.com/ogomr/items/493e10c424e9d6bd2028
reduxアプリの雛形生成
reduxを使用するためにジェネレーターでアプリの雛形を生成して、 楽しましょう。
Node.js/NPMを使って、 yeoman reduxジェネレーターをインストール。
$ npm install -g yo $ npm install -g generator-redux
ジェネレーターを使ってプロジェクトの雛形を生成します。
$ yo redux ? What's the name of your application? Counter ? Describe your application in one sentence: ... ? Which port would you like to run on? 3000 ? Install dependencies? Yes
jsディレクトリはこんな感じ。
- actions
- 「何が起きた」ということについての記述
- components
- コンポーネント
- containers
- メイン部分
- reducers
- Actionに従ったステートの更新を記述
- store
- ActionとReducerをつなげる
- utils
- デバグツール
チュートリアル
今回作るCounterに必要なのはcomponents, reducers, index.jsです。
npm start
を実行してから、 http://localhost:3000 を開きましょう。
- まずアプリの起点となる部分を記述します。
js/index.js
import React from 'react'; import ReactDOM from 'react-dom'; import Counter from './components/Counter'; function render() { ReactDOM.render( <Counter />, document.getElementById('main') ); } render();
- Counterコンポーネントを記述します。
js/components/Counter.js
import React, { Component } from 'react'; export default class Counter extends Component { render() { return ( <div> <h3>Counter: </h3> <button> + </button> {' '} <button> - </button> </div> ); } }
ブラウザを確認しましょう。 もちろん、 まだReduxを使っていません。
- Reducerにアクションタイプによるstateの更新を指定します。
js/reducers/index.js
export default function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } }
- Storeを作ります。 以下のコードを追加しましょう。
js/index.js
import counter from './reducers/index'; import { createStore } from 'redux'; const store = createStore(counter);
tips
stateを取得する:
store.getState()
stateを更新するためのアクションを対応させる:
store.dispatch(action)
listenerを登録:
store.subscribe(listener)
- listener: actionが発送(dispatch)された時に呼び出されるコールバック関数。 この中で
getStore()
を呼び出せば現在のstateを簡単に取得することができる。
- listener: actionが発送(dispatch)された時に呼び出されるコールバック関数。 この中で
- stateを取得し、 Counterコンポーネントに流します。 また、 アクションを対応させます。
js/index.js
import React from 'react'; import ReactDOM from 'react-dom'; import Counter from './components/Counter'; import counter from './reducers/index'; import { createStore } from 'redux'; const store = createStore(counter); function render() { ReactDOM.render( <Counter value={store.getState()} onIncrement={() => store.dispatch({ type: 'INCREMENT' })} onDecrement={() => store.dispatch({ type: 'DECREMENT' })} />, document.getElementById('main') ); } render(); store.subscribe(render);
- 最後にコンポーネントのレンダリング部分を編集してCounterの完成です。
js/components/Counter.js
import React, { Component } from 'react'; export default class Counter extends Component { render() { const { value, onIncrement, onDecrement } = this.props; return ( <div> <h3>Counter: {value}</h3> <button onClick={onIncrement}> + </button> {' '} <button onClick={onDecrement}> - </button> </div> ); } }