LoginSignup
9
3

More than 5 years have passed since last update.

Redux は reducer から理解するのがわかりやすい

Last updated at Posted at 2019-02-02

いくつか解説を眺めてみたが、最初から全部の流れを概観しようという解説や、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 という単語が使われている。

MDNdocDemo
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オブジェクトでしかない。

action
{
  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()))

状態の監視ができる。

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3