applyMiddleware
Middleware is the suggested way to extend Redux with custom functionality. Middleware lets you wrap the store's dispatch
method for fun and profit. The key feature of middleware is that it is composable. Multiple middleware can be combined together, where each middleware requires no knowledge of what comes before or after it in the chain.
The most common use case for middleware is to support asynchronous actions without much boilerplate code or a dependency on a library like Rx. It does so by letting you dispatch async actions in addition to normal actions.
For example, redux-thunk lets the action creators invert control by dispatching functions. They would receive dispatch
as an argument and may call it asynchronously. Such functions are called thunks. Another example of middleware is redux-promise. It lets you dispatch a Promise async action, and dispatches a normal action when the Promise resolves.
Middleware is not baked into createStore
and is not a fundamental part of the Redux architecture, but we consider it useful enough to be supported right in the core. This way, there is a single standard way to extend dispatch
in the ecosystem, and different middleware may compete in expressiveness and utility.
Arguments
...middleware
(arguments): Functions that conform to the Redux middleware API. Each middleware receivesStore
'sdispatch
andgetState
functions as named arguments, and returns a function. That function will be given thenext
middleware's dispatch method, and is expected to return a function ofaction
callingnext(action)
with a potentially different argument, or at a different time, or maybe not calling it at all. The last middleware in the chain will receive the real store'sdispatch
method as thenext
parameter, thus ending the chain. So, the middleware signature is({ getState, dispatch }) => next => action
.
Returns
(Function) A store enhancer that applies the given middleware. The store enhancer signature is createStore => createStore
but the easiest way to apply it is to pass it to createStore()
as the last enhancer
argument.
Example: Custom Logger Middleware
Example: Using Thunk Middleware for Async Actions
Tips
Middleware only wraps the store's
dispatch
function. Technically, anything a middleware can do, you can do manually by wrapping everydispatch
call, but it's easier to manage this in a single place and define action transformations on the scale of the whole project.If you use other store enhancers in addition to
applyMiddleware
, make sure to putapplyMiddleware
before them in the composition chain because the middleware is potentially asynchronous. For example, it should go before redux-devtools because otherwise the DevTools won't see the raw actions emitted by the Promise middleware and such.If you want to conditionally apply a middleware, make sure to only import it when it's needed:
This makes it easier for bundling tools to cut out unneeded modules and reduces the size of your builds.
Ever wondered what
applyMiddleware
itself is? It ought to be an extension mechanism more powerful than the middleware itself. Indeed,applyMiddleware
is an example of the most powerful Redux extension mechanism called store enhancers. It is highly unlikely you'll ever want to write a store enhancer yourself. Another example of a store enhancer is redux-devtools. Middleware is less powerful than a store enhancer, but it is easier to write.Middleware sounds much more complicated than it really is. The only way to really understand middleware is to see how the existing middleware works, and try to write your own. The function nesting can be intimidating, but most of the middleware you'll find are, in fact, 10-liners, and the nesting and composability is what makes the middleware system powerful.
To apply multiple store enhancers, you may use
compose()
.
Last updated