Redux Documentation の Data Flow の超訳です。
データフロー
Redux アーキテクチャは 厳密な一方向性データフロー 周りを解決するものです。
これはアプリケーション内におけるすべてのデータが同じライフサイクルパターンに従うことを意味していて、アプリのロジックがより予測可能な、理解がしやすいものになるということです。また、データの正規化を促進するので、気づかないうちにまったく同じだが独立したコピーが複数あるといったようなことがなくなります。
もしまだ納得していないようなら、動機 と Flux の事例 を読んでみてください。一方向性データフローに賛同する思わず引き込まれるような主張があります。 Redux は Flux ではありません が、同一の重要な利益をもたらします。
Redux アプリにおいてデータライフサイクルは以下の四つのステップに従います。
-
store.dispatch(action)
を 呼び出します 。
アクション は 何が起きたか を示すプレーンオブジェクトです。
{ type: 'LIKE_ARTICLE', articleId: 42 };
{ type: 'FETCH_USER_SUCCESS', response: { id: 3, name: 'Megan' } };
{ type: 'ADD_TODO', text: 'Redux のドキュメントを読む。'};
アクションはニュースの非常に短い要約のように考えましょう。
"メアリーは42条が好きだ。" または "'Redux のドキュメントを読む' がTODOリストに追加された。" といった感じです。
コンポーネントや XHR コールバックもしくはスケジュールされたインターバルの中でなど、アプリ内のどこからでも store.dispatch(action)
を呼び出すことができます。
- Redux のストアは渡されたレジューサ関数を呼び出します。
ストアは二つの引数をレジューサに渡します。現在のステートツリーとアクションです。例えば、TODOアプリでは、ルートレジューサが以下のように受け取ります。
// 現在のアプリケーションのステート(TODOのリストと選択されたフィルター)
let previousState = {
visibleTodoFilter: 'SHOW_ALL',
todos: [{
text: 'Read the docs.',
complete: false
}]
};
// 実行されるアクション(TODOの追加)
let action = {
type: 'ADD_TODO',
text: 'Understand the flow.'
};
// レジューサは次のアプリケーションのステートを返す
let nextState = todoApp(previousState, action);
レジューサはピュア関数であることに注意してください。次のステートを 計算する だけです。同じ入力であれば常に同じ出力を生成するという完全に予測可能なものでなくてはなりません。APIの呼び出しやルーターの遷移のようないずれの副作用も起こしてはなりません。それらはアクションがディスパッチされる前に行うべきです。
- ルートレジューサは複数のレジューサの出力を一つのステートツリーに結合します。
ルートレジューサの構成は完全に自由です。 Redux は ステートツリーの一枝をそれぞれ管理する関数にルートレジューサを ”分割する” ために有用な combineReducers()
というヘルパー関数を提供しています。
これから combineReducers()
がどのように動作するかを示します。二つのレジューサがあり、一つはTODOリストのためのもので、もう一つは現在選択されたフィルター設定のためのものです。
function todos(state = [], action) {
// 何らかの計算...
return nextState;
}
function visibleTodoFilter(state = 'SHOW_ALL', action) {
// 何らかの計算...
return nextState;
}
let todoApp = combineReducers({
todos,
visibleTodoFilter
});
アクションを起こしたとき、 combineReducers
によって返された todoApp
は両方のレジューサを呼び出します。
let nextTodos = todos(state.todos, action);
let nextVisibleTodoFilter = visibleTodoFilter(state.visibleTodoFilter, action);
二つの結果セットは一つのステートツリーに結合されます。
return {
todos: nextTodos,
visibleTodoFilter: nextVisibleTodoFilter
};
combineReducers()
は手軽なヘルパーユーティリティですが、必ずしも使う必要はありません。ルートレジューサは自由に記述してください!
- Redux のストアはルートレジューサが返す完全なステートツリーを保存します。
この新しいツリーは今やアプリの次のステートです! store.subscribe(listener)
で登録されたすべてのリスナーが呼び出されるでしょう。リスナーは現在のステートを取得するために store.getState()
を呼び出すでしょう。
これで新しいステートを反映するためにUIを更新できるようになりました。 React Redux のようなバインディングを使っているならば、ここが component.setState(newState)
を呼び出すときです。
次の節では
Redux がどのように動作するか把握したので、 Reactアプリに繋げましょう。
上級者のためのメモ
既に基本的な概念に精通していてこのチュートリアルを完了しているならば、
非同期アクション がレジューサに到達する前にミドルウェア(middleware)によってどのように変換されているのかについて学ぶため、
高度なチュートリアル 内の 非同期フロー を確認しましょう。