ref: redux/src/appltMiddleware, redux/src/compose.js, redux-thunk/src/index.js
What is middleware
Middleware is an abstract layer before action dispatching. For example, Redux-thunk is a middleware that can handle action which is not a plain object.
The implementation of redux-thunk is really elegant, yet a little bit confused. Let’s take a look.
How does applyMiddleware work?
Let’s look at the source code first:
// applyMiddleware.js
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer)
var dispatch = store.dispatch
var chain = []
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
// compose.js
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
const last = funcs[funcs.length - 1]
const rest = funcs.slice(0, -1)
return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}
Here is what happens when call applyMiddleware:
- Initialize store and dispatch, which will be used later.
- Clarify middleware_api, pass it into each middleware, and collect the results.
- Compose these middlewares, pass dispatch into this composed function. The result is a new dispatch function new_dispatch.
Then we dispatch action with new_dispatch function. Middlewares applied!
My previous note explains how compose works.