3

E.g. for certain actions, I want the reducers to process it before the epics do. And vice-versa for other actions. Is there a way to do this?

Leo Jiang
  • 24,497
  • 49
  • 154
  • 284
  • As per [specs](https://redux-observable.js.org/docs/basics/Epics.html), epics run *after* the reducers. What are you trying to achieve? Do you want an action to be fired when data changes? [This answer](https://stackoverflow.com/a/36558267/2764255) provides some insight on that. – Nikos Paraskevopoulos Jul 10 '17 at 12:57
  • @NikosParaskevopoulos in an epic, I'm dispatching an action that creates a promise. When the promise succeeds, I want to dispatch another action before the reducer process it. I'm doing this because I want the second action to behave differently depending on how it was dispatched. – Leo Jiang Jul 10 '17 at 18:01
  • @LeoJiang hmm it's not clear what you're trying to do still. What do you mean by "I want to dispatch another action before the reducer process it" ? Maybe we'll understand better if you describe _what_ you want to accomplish, not _how_ you think you should accomplish it? i.e. "I'm doing this because I want the second action to behave differently depending on how it was dispatched" this is close, but doesn't say why. With the provided info so far this all seems like an odd requirement. – jayphelps Jul 10 '17 at 19:56
  • There's an action `FETCH_USERS` which creates a network request. When the network request finishes, `FETCH_USERS_FULFILLED` is dispatched and a reducer appends the fetched users to the list of users to display. There's also an action `FILTER_USERS`, which reuses `FETCH_USERS` to fetch a list of users, but with filters applied. However, before the reducer appends the fetched users, I want to clear the list of users to display. This way, for filtering, fetched users replace the existing ones instead of appending to them. (continued) – Leo Jiang Jul 10 '17 at 21:43
  • I want to wait until the network request succeeds before clearing the users because I think it looks better to have a greyed out list of users than having a loading screen. – Leo Jiang Jul 10 '17 at 21:44

2 Answers2

5

As far as I see, you can't modify this - the reducers will always run first. The relevant chunk of redux-observable is:

  return action => {
    const result = next(action);
    input$.next(action);
    return result;
  };

The middleware will always pass the action on to the next middleware in the pipeline first, thus causing it to reach the reducers. Only after that returns does it feed the action into the epics. Redux-Saga does the exact same thing.

markerikson
  • 63,178
  • 10
  • 141
  • 157
  • 3
    To add to this, it is [specified](https://redux-observable.js.org/docs/basics/Epics.html) that epics run *after* the reducers: *"Epics run alongside the normal Redux dispatch channel, after the reducers have already received them[...]"*. – Nikos Paraskevopoulos Jul 10 '17 at 12:50
0

For any action that you want the epic to run before the reducer, make 2 actions.

Action A: Dispatch this in the app, watch for it in the epic. Do not do anything with it in the reducer, if appropriate.

Action B: Dispatch this in the Epic if Action A meets the right conditions. Handle this one in the reducer.

meticoeus
  • 543
  • 4
  • 9
  • Does it make sense that this causes the store to broadcast when nothing changed for Action A? – fionbio Feb 21 '19 at 13:26
  • @fionbio I'm not sure that it always makes sense if there really are no changes to make in the reducer. I think that It usually does just for the sake of a simpler, consistent API in the app. When I use this pattern, Action A usually toggles a boolean flag like "isLoading: true", then the epic will dispatch a success or fail action, and each will reset the flag to "false" along with any other changes to state. – meticoeus Feb 22 '19 at 16:59
  • Thanks. After exploring redux - I aborted and went Mobx and I'm a much happier human now. – fionbio Feb 22 '19 at 20:47