はじめに
今更ながらですが、今個人的に作っているものにReact+Reduxを導入するついでに、いつでも確認できるように各役割についてのメモを残しておきます。間違いなどございましたら、コメントにてご指摘お待ちしておりますm(_ _)m
ほぼこちらに英語で書いてあることになります。Reduxを使ってみたい方はこちらのbasicsという内容を追っていくといいと思います。
http://redux.js.org/docs/basics/
Action
(http://redux.js.org/docs/basics/Actions.html)
アクションは『何か』が起こった時、Storeに『どんなデータ』を利用するかということを定義します。
ActionCreatorであるstore.dispatch()を使ってStoreに送信しますが、storeについてはこの記事の最後にまとめています。(※ こちら)
ただし、アプリケーションの状態がどのように変化するかはここでは指定しません。(→Reducerがやること)
あくまでどんな挙動があるかだけを定義します。
Overview
Actionの定義
export const ADD_TODO = 'ADD_TODO'
export function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
type以外のアクションオブジェクトの構造は、あなた次第です。
(Other than type, the structure of an action object is really up to you.)
とのこと。
Action Creators
Action Creatorsは、Actionを作成する関数です。
トラディショナルなfluxでは大抵下記のようになっているものを
function addTodoWithDispatch(text) {
const action = {
type: ADD_TODO,
text
}
dispatch(action)
}
reduxではstore.dispatch()のように書けます。
react-reduxを使えばconnect()という関数を使って簡単に利用できます。
とのこと。
普段はAction Creatorということを意識せずとも使うことができそうですね。
Reducers
(http://redux.js.org/docs/basics/Reducers.html)
Reducerは本家サイトでは下記のような言葉を交えて説明されています。
Stateの状態をデザインする - Designing the State Shape (http://redux.js.org/docs/basics/Reducers.html#designing-the-state-shape)
アクションをハンドリングする - Handling Actions (http://redux.js.org/docs/basics/Reducers.html#handling-actions)
Reducerは、前の状態とアクションを取り、次の状態を返す純粋な関数です。
(previousState, action) => newState
(要は、アクションから値を受け取ってStateに置けるように変換する(Reduceする)からReducerと呼ぶようです。)
Reducerでしてはいけないこと (Things you should never do inside a reducer)
結構重要です。
- 引数が不自然に変更されるようなことはしてはいけません(Mutate its arguments;)
- API問い合わせやルーティングのような副作用を生み出す実装をしてはいけません(Perform side effects like API calls and routing transitions;)
- 純粋関数ではない関数を呼んではいけません(Math.random()やDate.Now()など)(Call non-pure functions, e.g. Date.now() or Math.random())
つまりは同じ引数を渡したら、常に同じ結果になるようにしなさいと。
(Given the same arguments, it should calculate the next state and return it.
No surprises. No side effects. No API calls. No mutations. Just a calculation.)
Overview
Reducerの設定
import { VisibilityFilters } from './actions'
const initialState = {
visibilityFilter: VisibilityFilters.SHOW_ALL,
todos: []
}
function todoApp(state, action) {
if (typeof state === 'undefined') {
return initialState
}
// For now, don't handle any actions
// and just return the state given to us.
return state
}
Reducerの複数設定
Reducerは複数設定することが可能です。
import { combineReducers } from 'redux'
const todoApp = combineReducers({
visibilityFilter,
todos
})
export default todoApp
Store
(http://redux.js.org/docs/basics/Store.html)
前のセクション(Action,Reducer)では、「起こったこと」に関する事実を表すActionと、それらのアクションに従って状態を更新するReducerを定義しました。
Storeはそれらを結びつける責任があります。
Reduxアプリケーションには1つのStoreしかないことに注意してください。(It's important to note that you'll only have a single store in a Redux application. )
データ処理ロジックを分割したい場合は、storeを複数使う代わりにreducer compositionを使用します。
Storeの役割
- アプリケーションの状態(state)を保持します。(Holds application state;)
- getState()を介してstateへのアクセスを許可します。(Allows access to state via getState();)
- 状態をdispatch(アクション)によって更新できるようにする。(Allows state to be updated via dispatch(action);)
- subscribe(listener)を介してlistenerを登録します。(Registers listeners via subscribe(listener);)
- subscribe(listener)によって返された関数を介して、listenerの登録解除を処理します。(Handles unregistering of listeners via the function returned by subscribe(listener).)
Overview
Storeの作成について
import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp)
Dispatching Actions
『状態をdispatch(アクション)によって更新できるようにする。』の部分ですね。
// Dispatch some actions
store.dispatch(addTodo('Learn about actions'))
流れのまとめ
ここまで理解できると、こちらの図解などが理解を助けてくれるのではないでしょうか。
画像引用元 : http://www.slideshare.net/nikgraf/react-redux-introduction (スライド33枚目)
補足
APIコールについては
http://redux.js.org/docs/advanced/
を読み進めると良いみたいです。こちらはまた個人的にメモが必要になったら投稿したいと思います。
追記: http://redux.js.org/docs/basics/UsageWithReact.html も同じノリでまとめました
ReduxのPresentational ComponentsとContainer Componentsの役割の(個人的な)整理メモ