Search code examples
reactjsreduxrxjsredux-observable

Redux-observable: how a component can subscribe to react when action is completed?


Suppose this demo code:

const pingEpic = action$ => action$.pipe(
  filter(action => action.type === 'PING'),
  delay(1000), // Asynchronously wait 1000ms then continue
  mapTo({ type: 'PONG' })
);

// later...
dispatch({ type: 'PING' });

const pingReducer = (state = {}, action) => {
  switch (action.type) {
    case 'PING':
      return state;

    case 'PONG':
      return state;

    default:
      return state;
  }
};

In a specific component, which suppose has nothing to do with dispatching PING or PONG neither use any redux state, I would like to somehow subscribe to the actions lifecycle and when the PONG action has completed (i.e. has been processed by the reducer) it executes a callback. Something like:

const myComponent = () => {
  ofActionSuccessful('PONG').subscribe( () => console.log('PONG has just completed'));
}

Something like: https://www.ngxs.io/advanced/action-handlers

How could I achieve that?

I don't want to link some logic in the reducer, because it is something strictly related to that component and has nothing to do with the store.


Solution

  • From the redux-observable docs:

    Epics run alongside the normal Redux dispatch channel, after the reducers have already received them--so you cannot "swallow" an incoming action. Actions always run through your reducers before your Epics even receive them.

    So we can use epics to get the "PONG" signal.

    const allActions$ = new Subject();
    
    // This must be merged into your root epic.
    export const tapAllActions = (action$) =>
      action$.pipe(tap(allActions$), concatMapTo(EMPTY));
    
    export const ofActionSuccessful = (actionType) =>
      allActions$.pipe(filter(({ type }) => type === actionType));