Skip to content

Commit 8c9e5d6

Browse files
committed
feat(redux): middlewareの動作について
1 parent 148b461 commit 8c9e5d6

File tree

3 files changed

+81
-5
lines changed

3 files changed

+81
-5
lines changed

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
* [ESLint](ja/ESLint/README.md)
77
* [Connect](ja/connect/README.md)
88
* [gulp](ja/gulp/README.md)
9+
* [Redux](ja/Redux/README.md)

ja/Redux/README.md

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Reduxには[Three Principles](http://redux.js.org/docs/introduction/ThreePrincip
2121
- [Read Me | Redux](http://redux.js.org/)
2222
- [Getting Started with Redux - Course by @dan_abramov @eggheadio](https://egghead.io/series/getting-started-with-redux)
2323

24-
Reduxの使い方についてはここでは解説しませんが、Reduxの拡張である _Middleware_ も、この三原則に基づいた仕組みとなっています。
24+
Reduxの使い方についてはここでは解説しませんが、Reduxの拡張機能となる _Middleware_ も、この三原則に基づいた仕組みとなっています。
2525

2626
_Middleware_ という名前からも分かるように、[connect](../connect/README.md)の仕組みと類似点があります。
2727
[connect](../connect/README.md)の違いを意識しながら、Reduxの _Middleware_ の仕組みを見ていきましょう。
@@ -50,7 +50,82 @@ Reduxの例として次のようなコードを見てみます。
5050

5151
`dispatch(action)` -> (_Middleware_ の処理) -> reducerにより新しいStateの作成 -> (Stateが変わったら) -> `subscribe`で登録したコールバックを呼ぶ
5252

53-
次は`applyMiddleware`がどのように _Middleware_ を登録しているのかを見ていきましょう。
53+
次は _Middleware_ はどういう拡張を行えるのかを見ていきます。
54+
55+
## Middleware
56+
57+
Reduxでは第三者が拡張できる仕組みを _Middleware_ と呼んでいます。
58+
59+
- [Middleware | Redux](http://redux.js.org/docs/advanced/Middleware.html "Middleware | Redux")
60+
61+
どのような拡張を _Middleware_ で書けるのか、実際の例を見てみます。
62+
次の _Middleware_ はStoreがdispatchしたActionと、その前後でStateにどういう変更があったのかを出力するロガーです。
63+
64+
[import, logger.js](../../src/Redux/logger.js)
65+
66+
この _Middleware_ は次のようにReduxに対して適用できます。
67+
68+
```js
69+
import {createStore, applyMiddleware} from "redux";
70+
const createStoreWithMiddleware = applyMiddleware(createLogger())(createStore);
71+
```
72+
73+
この時、見た目上は `store` に対して _Middleware_ が適用されているように見えますが、
74+
実際には`store.dispatch`に対して適用され、拡張された`dispatch`メソッドが作成されています。
75+
76+
これにより、以下のように`dispatch`を実行する際に _Middleware_ の処理が実行されてから、
77+
実際に`dispatch`されるというのがReduxの _Middleware_ による拡張のポイントになっています。
78+
79+
```js
80+
store.dispatch({
81+
type: "AddTodo",
82+
title: "Todo title"
83+
});
84+
```
85+
86+
さきほどの`logger.js`を見てみます。
87+
88+
```js
89+
export default function createLogger(options = defaultOptions) {
90+
const logger = options.logger || defaultOptions.logger;
91+
return store => next => action => {
92+
logger.log(action);
93+
const value = next(action);
94+
logger.log(store.getState());
95+
return value;
96+
};
97+
}
98+
```
99+
100+
`createLogger`は、loggerにオプションを渡すためのものなので置いておき、
101+
`return`している高階関数の連なりが _Middleware_ の本体となります。
102+
103+
```js
104+
const middleware = store => next => action => {}
105+
```
106+
107+
上記のArrowFunctionの連なりが一見すると何をしているのかが分かりにくいですが、
108+
これは下記のように展開することができます。
109+
110+
```js
111+
const middleware = (store) => {
112+
return (next) => {
113+
return (action) => {
114+
// Middlewareの処理
115+
}
116+
}
117+
}
118+
```
119+
120+
ただ単に関数を返す関数(高階関数)を作っているだけだと分かります。
121+
122+
これを踏まえて logger.js をもう一度見てみると、`next(action)` の前後にログ表示を挟んでいることが分かります。
123+
124+
[import, logger.js](../../src/Redux/logger.js)
125+
126+
この場合の `next``dispatch` と言い換えても問題ありませんが、複数の _Middleware_ を適応した場合は、
127+
**次の** _Middleware_ を呼び出すという事を表現しています。
128+
54129

55130
## どういう仕組み?
56131

src/Redux/redux-example.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {createStore, applyMiddleware} from "redux";
2-
import logger from "./logger";
3-
import crashReporter from "./timestamp";
2+
import createLogger from "./logger";
3+
import timestamp from "./timestamp";
44
// 4. Actionを受け取り新しいStateを返すReducer関数
55
const reducer = (state = {}, action) => {
66
switch (action.type) {
@@ -11,7 +11,7 @@ const reducer = (state = {}, action) => {
1111
}
1212
};
1313
// 1. `logger`と`crashReporter`のmiddlewareを適応した`createStore`関数を作る
14-
const createStoreWithMiddleware = applyMiddleware(logger, crashReporter)(createStore);
14+
const createStoreWithMiddleware = applyMiddleware(createLogger(), timestamp)(createStore);
1515

1616
// 2. Reducerを登録したStoreを作成
1717
const store = createStoreWithMiddleware(reducer);

0 commit comments

Comments
 (0)