Actionis an object with a field
type. More usefully, an
Actiondescribes what change should be made to the application state.
Reduceris a function that, given an existing state and an
Action, produces the state that should exist after the
Actionhas been applied. If an
Actiondescribes what changes should be made, a
Reducerdescribes how that change should be made.
getState()) and provides a
dispatchfunction that allows us to send
Actions to our
Reducers. A simplified interface would be something like this:
createStorefunction, which, well, creates our
Store. More importantly, it contains some important variables that will get used by functions like
dispatchand other functions are also created in
createStore, meaning that these variables are closed over, i.e.
dispatchwill have access to these variables, and we'll see how it uses them next.
dispatchfunction is when I first saw it (though I don't really know what I expected). You'll see that is uses those variables defined in
createStorefrom before. Here's a stripped down version, showing just the meat of it:
currentStateto the new application state the reducer spit out in response to an
Reducer– don't let the variable name
currentReducerthrow you off. It's only "current", because of some functionality Redux provides for dynamically loading reducers that isn't relevant for us here. Speaking of which, how does Redux make all our different reducers act as one?
combineReducersfunction, which takes a object-map of sub-reducers and returns a single function, i.e. a
Reducer, that invokes all of them. Here's a simplified version of
dispatch, this is actually pretty simple. We go through all the sub-reducers we have, pass it existing state and the action, and collect all those results into a new state object.
dispatchfunction to add to its capabilities.
MiddlewareAPIis what gives our middleware access to
dispatchand a way to get the current state. Simple enough.
dispatchthat has a handle to the next dispatch in the chain. So really, our middlewares are just custom
dispatchs that handle the action in some way and then pass the action off to the next dispatch. You may need to stew on that for a minute and make sure you understand it.
dispatchwe create needs access to the
MiddlewareAPIand a handle to the next middleware/dispatch in our middleware chain. All that happens in
Middlewareis a curried function with three layers – an
Dispatch, and finally an
applyMiddleware'peels off' two layers of our
Middlewares, creating a single function that becomes our Redux Store's
MiddlewareAPIfrom our newly created store and give all our middlewares access to it with
middlewares.map(middleware => middleware(middlewareAPI)).
Middlewares together with the
composeserially chains multiple functions together into a single function. It's actually not terribly complicated, but it's easier to understand by example:
compose(F, G, H)turns into
(...args) => F(G(H(...args))). (Note that in this chain, the parameters that
Haccepts become the parameters that our newly created chain accepts.) Finally, we call this composed
Middlewarechain with the default
dispatchfrom our store.
middlewaresare just normal
Action => any) that have a handle to
nexti.e. the next
dispatchin the chain. (That means we have to make sure our
nextat some point, or the dispatch won't make it to the end i.e. our
dispatchin the chain. Here's some pseudocode that outlines how that application would go.
dispatchwill look like. This is, again, pseudocode to illustrate how the data flows, not the definitions of the functions.
applyMiddlewareis returning our
store, but with
dispatchoverridden to be our custom