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

How to build Rails5 API + Redux ToDo Application その3

プログラミング Ruby on Rails JavaScript React Redux

前回はReactでToDOクライアントを実装しました。

kogoto.hatenablog.com

で、これをRedux化してみます。

いきなりAPI叩くとややっこしいので、まずはクライアント単独で動作するものを作成してみます。

ソースコードはこちら。

github.com

create-react-app使ってるので、clientの下でnpm installしてから

$ npm start

ってやるとブラウザが起動して実行開始されます。

モジュールのインストール

$ npm install --save redux react-redux redux-actions

ディレクトリの再構成

%RAILS_ROOT%にclientフォルダを作成しそこにプロジェクトを配置します。
また、Reduxの作法にしたがったディレクトリ構成にします。

src
├── App.js
├── actions
│   └── index.js
├── components
│   └── Todo.js
├── constants
│   └── ActionTypes.js
├── containers
│   ├── TodoForm.js
│   └── TodoList.js
├── index.js
├── reducers
│   ├── form.js
│   ├── index.js
│   └── todos.js
└── store
    └── index.js

Actionの洗い出し

今回のToDOで発生するActionをリストアップします。

  • 優先順位変更
  • タイトル入力
  • 登録処理
  • 削除処理
  • 完了⇔未完了の切り替え

これを元にActionを生成します。

// constants/ActionTypes.js

export const CHANGE_ORDER = 'CHANGE_ORDER'
export const CHANGE_TITLE = 'CHANGE_TITLE'
export const ADD_TODO = 'ADD_TODO'
export const DELETE_TODO = 'DELETE_TODO'
export const TOGGLE_TODO = 'TOGGLE_TODO'
// actions/index.js

import { createAction } from 'redux-actions'
import * as types from '../constants/ActionTypes'

export const changeOrder = createAction(types.CHANGE_ORDER)
export const changeTitle = createAction(types.CHANGE_TITLE)
export const addTodo = createAction(types.ADD_TODO)
export const deleteTodo = createAction(types.DELETE_TODO)
export const toggleTodo = createAction(types.TOGGLE_TODO)

Stateの洗い出し

各コンテナ・コンポーネントがもつStateをリストアップします。

TodoForm

  • 入力中のタイトル
  • 入力中の優先順位
  • 登録ボタンの有効/無効状態

TodoList

  • 登録されたToDO一覧

Todo

  • タイトル
  • 優先順位
  • 完了/未完了状態

で、これを元にReducerを作成します。

// reducers/form.js

const initialState = {
  title: '',
  order: 1,
  completed: false,
  disabled: true
}

const form = handleActions({
  /* ... */
}, initialState)

export default form
// reducers/todos.js

const initialState = {
  title: '',
  order: 1,
  completed: false
}

const todo = handleActions({
  /* ... */
}, initialState)

const todos = handleActions({
  /* ... */
}, [])

export default todos

これらをcombineReducersでくっつけてstoreとします。

と書いてるとだんだんややこしくなってくるので、図にしてみました。

f:id:ktdk:20160728182352p:plain

ユーザーからの操作でReducerに対してActionが発行され、Stateが更新されます。
更新されたStateで再描画される、ってなわけです。

ひとまずRedux方式になったので、次回はこれにAPIを叩かせたいと思います。