redux-saga: Saga cannot catch actions dispatched by store enhancers

I need to use store enhancer (reactReduxFirebase from react-redux-firebase) in my redux app. This enhancer dispatches an action, it looks more or less like this (much simplified):

const reactReduxFirebase = (next) => {
  return (reducer, initialState, middleware) => {
    const store = next(reducer, initialState, middleware);
    store.dispatch({
      type: 'DUMMY_ACTION'
    });
    return store;
  }
}

// usage
const sagaMiddleware = createSagaMiddleware();
const middleware = [sagaMiddleware];
const store = createStore(
  reducer,
  initialState,
  compose(
    applyMiddleware(...middleware),
    reactReduxFirebase
  )
);
sagaMiddleware.run(sagas);

// sagas.js
function* handle(action) {
  console.log(action);
}

function* saga() {
  yield takeEvery('*', handle);
}

export default saga;

I want saga to listen to all actions and console.log them, but it doesn’t catch ‘DUMMY_ACTION’ dispatched by enhancer, because it’s being dispatched before saga starts to listen (sagaMiddleware.run(sagas);). From redux-saga docs it seems that saga must be run after applyMiddleware, so I cannot make saga run before enhancer. Is there any way to make it work, so the saga will catch an action from enhancer as well?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 12
  • Comments: 16 (7 by maintainers)

Most upvoted comments

I’m interested in experimenting with a redux-saga enhancer but the benefits need to be more clear. This would involve new code and with that testing, debugging, and docs; a non-trivial amount of work. Also, we wouldn’t replace our current middleware system for it, this would have to be additive.

Furthermore, after reading the electron-redux enchancer, I’m confused why they decided to make it an enhancer. I could be missing something, but the way it works is the enhancer appears to be listening for IPC events and dispatching actions. They also monkey-patch dispatch to forward actions to other redux stores via IPC. If that’s right then this library could be implemented as middleware.

There could be other reasons why it’s an enhancer and not middleware, but it doesn’t seem obvious to me with a cursory read of their code.

I’ve also implemented something similar myself a few years ago in electron. It wasn’t that hard to manage on our own without this library. Not ideal, but food for thought nonetheless.

It would be great if redux-saga wasn’t such a stickler about where actions originate from.

It’s not that - we can’t even know the origin of actions. The point here was that there are some init-time actions dispatched from enhancers and those are simply dispatched before saga gets “installed”. It’s a timing~ issue.

Would you be open to re-opening this issue or https://github.com/redux-saga/redux-saga/issues/1056 for further discussion? Or is it just all but impossible to consider a change to an enhancer-based implementation so far into development? I’m not really sure how extensive a rewrite that would entail or just how dangerous it would be.

I don’t have such plans - simply because I don’t have time to fully evaluate this etc. Perhaps @neurosnap would be more interested in this (or maybe not).

This isn’t the first time I’ve hit an issue like this with redux-saga, and I just love it so much - it would be great for it to be even more flexible.

I understand that this is probably very annoying when it happens - but OTOH this doesn’t really happen a lot. Although, when it does, it’s hard to tell on the spot what happens. That’s why I’m not saying that such a change would be impossible - it’s just that it’s a delicate one. For example, at the moment, we recommend using Saga as your last middleware but this implies that it should be the very first thing installed in the chain (otherwise you always have a chance of missing some init-time action).

Is there any hope for this route, without doing such an extensive rewrite? Clunkiness to handle edge cases is arguably better than not handling the edge cases, but then again it’s also arguable that it’s not better.

If you’d invest some time to prepare a PoC for this - we could consider this route.

@Slapbox based on the comment here I think this just isn’t solvable in the current API - middlewares (and you install redux-saga as a middleware) can’t listen for actions dispatched from store enhancers like that. Perhaps redux-saga should have been a store enhancer and that could fix issues like this - but I’m not sure how safe changing this would be and what kind of unexpected problems we could end up with.