Search code examples
javascriptreduxngredux

Listen for dispatched action in Redux


I'm wondering if there's a way to listen for an action that's been successfully dispatched in redux?

In the ngxs state management library for Angular, I can do the following:

ngOnInit() {
  this.actions$
    .pipe(
      ofActionSuccessful(AddedThingToDo),
      map((event: AddedThingToDo) => event.thingToDo),
      tap(thingToDo => console.log('Action was successfully dispatched'))
    )
   .subscribe();
}

Where I can then perform an action when I know that AddedThingToDo has been successfully dispatched. This could be something like closing a modal, or perhaps dispatching another action.

I'm using ng-redux for Angular 1.x, however I think the principle should remain the same that it would for react redux.

The only way I've been getting around it is with a callback in my actions, but it feels very wrong:

export const addThingToDo = (model: IThingToDo, onSuccess?: (model: IThingToDo) => void) =>
  async (dispatch: Dispatch) => {
    dispatch(addingThingToDo());
    try {
      const createdItem = await api.post<IThingToDo>(url, model);
      dispatch(addedThingToDo(createdItem));
      if (onSuccess) {
        onSuccess(createdItem);
      }
    }
    catch (ex) {
      dispatch(addThingToDoFailure(ex));
    }
  };

Solution

  • Turns out redux-thunk supports returning promises, so I can just return a promise rather than use a callback method.

    export const addThingToDo = (model: IThingToDo) =>
      async (dispatch: Dispatch): Promise<IThingToDo> =>
        await new Promise<IThingToDo>(async (resolve, reject) => {
          dispatch(addingThingToDo());
          try {
            const newItem = await api.post<IThingToDo>(url, model);
            dispatch(addedThingToDo(newItem));
            resolve(newItem);
          } catch (ex) {
            dispatch(addThingToDoFailure(ex));
            reject(ex);
          }
        });
    
    
    this.addThingToDo(thingToDo)
      .then(t => navigateTo(`/things-to-do/${t.id}`));