Description
Preface: This may or may not be a bug in Redux.
Say you have a middleware that intercepts actions and emits async events to dispatch later on. We do something like this in redux-simple-router
:
function middleware(store) {
history.listen(location => { store.dispatch(updateLocation(location)) })
return next => action => {
if (action.type !== TRANSITION) {
return next(action)
}
const { method, arg } = action
history[method](arg)
}
}
The key bit is the history listener at the top. The middleware intercepts actions of type TRANSITION
and runs a history command (push
, for example). That comes back to us via the listener and we dispatch an updateLocation
action to update the store with the current location.
Now, let's say you have a little bit of analytics middleware that watches for updateLocation events and tells your analytics service there's a new page view. This works A-OK because store.dispatch
above has had the middleware applied to it and will include the analytics middleware in the dispatch.
Here's the problem: That listener fires when you're applying the middleware, so calling store.dispatch
is calling the un-middlewared dispatch
and our analytics middleware won't see any event.
Should Redux handle this? It might be better handled by the history middleware, or by the analytics middleware, or by a non-middleware approach. But it certainly does end up creating some confusion for users when code operates differently the first time you run it.