読者です 読者をやめる 読者になる 読者になる

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を簡単に取得することができる。

 

  • 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>
    );
  }
}