1

I am having the following 3 actions:

export const createSite = createAction(
  '[Site] Create Site',
  props<{ site: SiteRequest }>()
);

export const createSiteSuccess = createAction(
  '[Site] Create Site Success',
  props<{ site: SiteResponse }>()
);

export const createSiteFailed = createAction(
  '[Site] Create Site Failed',
  props<{ error: any }>()
);

My reducer:

export const SITES_FEATURE_KEY = 'sites';

export interface State extends EntityState<SiteResponse> {
  selectedId?: string | number;
  loaded: boolean;
  loading: boolean;
  error?: string | null;
}

export interface SitesPartialState {
  readonly [SITES_FEATURE_KEY]: State;
}

export const sitesAdapter: EntityAdapter<SiteResponse> = createEntityAdapter<SiteResponse>();

export const initialState: State = sitesAdapter.getInitialState({
  loaded: false,
  loading: false,
});

const sitesReducer = createReducer(
  initialState,
  on(SitesActions.createSite, (state) => ({ ...state, loaded: false, loading: true, error: null })),
  on(SitesActions.createSiteSuccess, (state, { site }) =>
    sitesAdapter.addOne(site, { ...state, loaded: true, loading: false})
  ),
  on(SitesActions.createSiteFailed, (state, { error }) => ({
    ...state,
    error,
  }))
);

export function reducer(state: State | undefined, action: Action) {
  return sitesReducer(state, action);
}

My effects:

@Injectable()
export class SiteEffects {
 
  createSite$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SiteActions.createSite),
      exhaustMap((action) => this.siteService.createSite(action.siteRequest)
        .pipe(
          map(site => SiteActions.createSiteSuccess({ site })),
          catchError((error) => of(SiteActions.createSiteFailed({ error }))
        )
      )
    )
  );
 
  createSiteSuccess$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SiteActions.createSiteSuccess),
      tap(() => this.router.navigate['dashboard'])
    ),
    { dispatch: false }
  );

  constructor(
    private actions$: Actions,
    private siteService: SiteService,
    private router: Router,
  ) {}
}

When submitting the form by clicking on a button I dispatch the action [Site] Create Site and pass the data from the form to this action. With the code mentioned above, I am experiencing the following issues:

  • When I have both effects createSite$ and createSiteSuccess$ in my effects file, the createSite$ is even not triggered so my api call is not even done.

  • If I comment out the createSiteSuccess$ effect, the createSite$ effect is triggered and the api call is happening(returning a 201 with the site object). The returned site response object is also added to my entities array by the reducer but with this I don't have my createSiteSuccess$ effect which should route me back to my dashboard page on success.

  • If I remove the dispatch: false from the createSiteSuccess$ then the the createSite$ effect is triggered and the api call is happening but I am stuck in a loop which is normal because that is why the dispatch false needs to be there.

Is there anyone having an idea what I am doing wrong or what the issue could be?

Kind regards,

Gerry

innoveltec
  • 11
  • 1
  • 4
  • why not add the `this.router.navigate['dashboard']` before triggering `createSiteSuccess`? for the effect `createSite`? do you really need another effect just for triggering navigation? – Andres2142 Mar 03 '23 at 21:11
  • Thumbs up for the clean code. @Andres2131 technical possible, but then you violate single responsibility rule, if you go by this rule. – hmartini Apr 03 '23 at 21:52
  • Does something change, when you replace the tap(() => this.router.navigate(['dashboard'])) with tap(console.log)? – hmartini Apr 03 '23 at 22:03

0 Answers0