いくつか解説を眺めてみたが、最初から全部の流れを概観しようという解説や、action から入る解説は私にとって少しわかりにくかった。
少し理解が進んだ今、redux は reducer から理解すべきだ、と思う。
reducer を理解するといくつも疑問が生じる。その疑問を解消する形で理解の範囲を広げていく。
Reducer を理解する
(state, action) => newState
Reducer はただの関数だ。
一般的に (state, action) => newState
とあらわせる(シグネチャとして)。
日本語に翻訳するなら、
「状態と作用をとって新しい状態を返す関数」
あるいはもっと噛み砕いて、
「状態に作用を加えて新しい状態を作る関数」
とも言えるかもしれない。
もちろん、新しい状態にさらに作用を加えれば、また別の状態が生まれる。
(newState, anotherAction) => newState2
もちろんこれは副作用のない関数だ。
state と action の組み合わせが同一であるならば、何度呼んでも同じ newState が返ってくる。
Array.prototype.reduce との類似
Array.prototype.reduce()
という JavaScript の関数で例えてみよう。
時系列に沿って次のような action があって、なぜか配列に収まっていたとする。
[action1, action2, action3]
この action の配列によって作られる状態は次のようなものだ。
[action1, action2, action3].reduce((累積した状態, action) => {
// ...
// 状態に対して action が作用する処理
// const newState = ...
return newState // 新しい状態 = 次の累積した状態
}, 初期状態)
Array.prototype.reduce
は初期状態に対し、コールバックによる配列要素の処理を累積させていくものだ。
さて、ここで渡されるコールバックのことを reducer という。
MDN doc のデモ でも reducer という単語が使われている。
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
この reducer と Redux の reducer はほとんど同じものである。
ただ、Redux においては action は時系列に沿って順次やってくるものであって、最初からおとなしく配列におさまっているものではない。
生じる疑問
さて、 reducer は状態の変化を司るが、これだけで状態を管理をすることはできない。
以下の疑問が当然生じてくるだろう。
- reducer の返り値はどこに(誰が)保存するのか
- reducer はどうやって呼ぶのか
reducer の返り値はどこに(誰が)保存するのか
A. store
具体的には createStore
という関数から返されるオブジェクトである。
store = createStore(reducer[, 初期状態とかエンハンサとか])
// いろんな処理
store.getState() // reducer の最新の返り値、すなわち現在の状態を得る
reducer はどうやって呼ぶのか
A. store のメソッド経由で
このメソッドを dispatch という。
store.dispatch(action)
state は store が持っているので、渡す必要はない。
dispatch の名前の由来は知らないので知りたいが、別に知る必要もない気もする。
とりあえず、メソッドの名前だ。
その他のあったらいいな
ActionCreator
そもそも action とはなんぞや。
上の方では作用と言っていたけれど、作用を表現するための決まった形式がある。
具体的には次のようなJSオブジェクトでしかない。
{
type: 'ADD_OBJCET',
payload: object
}
ただ、この action を毎回作るのめんどくさい。
これを作る過程でいろんなロジックも必要になりそう。
それなら ActionCreator にまとめてしまえ。
// 上の action が返ってくるような関数 actionCreator を作っておく
store.dispatch(addObjectCreator(object))
ちょっとオシャレ(?)になると自分で作ったアクションをそのまま dispatch しちゃったりする。
基本的に自由だ。
redux に必要というより react-redux に必要(便利)。
subscribe
状態変化の通知が欲しかったらコールバックを渡して購読する。
実際には dispatch のたびにコールバックが呼ばれるらしい。
store.subscribe(() => console.log(store.getState()))
状態の監視ができる。