2

I have an effects function where I'm trying to pass data from my dispatched action as well as a separate selector to a function in a service, but I'm getting lost in the RXJS syntax. I'm pretty sure I'm not mapping the data correctly. Please see the relevant code.

// effects

 updateCohort$ = createEffect(() =>
    this.actions$.pipe(
        ofType(getCohortActions.updateActiveCohort.type),
        withLatestFrom(this.store.pipe(select(activeCohort))),
        map(([action, selector ]) => (
            this.cohortFeaturesServices.updateCohorts(action, selector)
        )),

// service

public updateCohorts(action, selector): Observable<any> {
    const url = `api/services/cohorts/frontend/`;

    return this.http.patch(`${url}/${selector.id}/`, action.changes);
}

Visual Studio Code underlines the entire function and I get the following error in my console.

Type 'Observable>' is not assignable to type 'Observable'. Property 'type' is missing in type 'Observable' but required in type 'Action'.

How can I fix my effect and successfully pass my action and my selector to my service call?

London804
  • 1,072
  • 1
  • 22
  • 47
  • Use my answer [here](https://stackoverflow.com/a/57612215/4711754) to debug the error though I can tell you straight away that you aren't returning an `Action` in the effect `updateCohort$`. Either use `{ dispatch: false }` to indicate the effect is for side only effects (i.e. no further action / state changes required) or return an `Observable` (use `map` within pipe to map to success action and `catchError` to map to `of(`error action`)`, the `of` being for keeping correct types – Andrew Allen Feb 12 '20 at 22:22
  • @AndrewAllen thanks for your reply. I've actually come across that answer before and I've been using it. Unfortunately, when I delete 'createEffect' nothing is highlighted so I'm not sure how to go about solving this. – London804 Feb 12 '20 at 22:43
  • That’s because there’s no coding error but like I say effects map actions to actions (most commonly a potentially failing action to its success/fail variants) or are explicitly side effects only in which case `{ dispatch: false }` is required. Read up on ngrx effects https://ngrx.io/guide/effects and know this diagram off by heart https://ngrx.io/guide/store#diagram – Andrew Allen Feb 12 '20 at 22:53
  • I’ll post an answer tomorrow and update my linked answer – Andrew Allen Feb 12 '20 at 22:54
  • This is not a good way to do that we use effect to call API – Tony Ngo Feb 13 '20 at 04:39
  • That's exactly what I'm trying to do. I'm trying to call an API from my effects function. – London804 Feb 13 '20 at 17:46

2 Answers2

1

You need to use switchMap/mergeMap/concatMap/exhaustMap to "unbox" observable coming from HTTP service -> result of switchMap -> map into action such as your effect must return actions(such as it is just a default effect with action dispatch).

Also, I suggest that the API method would have the changes as parameters, not an action.

updateCohort$ = createEffect(() =>
  this.actions$.pipe(
    ofType(getCohortActions.updateActiveCohort.type),
    withLatestFrom(this.store.pipe(select(activeCohort))),
    switchMap(([action, cohort]) =>
      this.cohortFeaturesServices.updateCohorts(action.changes, cohort)
    ),
    map((result: CohortUpdateResponse) => successCohortUpdateAction())
  )
)


public updateCohorts(changes: Partial<Cohort>, cohort: Cohort): Observable<CohortUpdateResponse> {
  const url = `api/services/cohorts/frontend/`;

  return this.http.patch(`${url}/${cohort.id}/`, changes);
}

Something like this.

P.S. added some "invented" types to show what is going on and where

P.S.S didn't check for typos in code, such wrote answer right in answer window

GL :)

andriishupta
  • 497
  • 4
  • 8
1

For anyone else they may come across the same issue I figured it out. I wasn't returning an action.

updateCohort$ = createEffect(() =>
    this.actions$.pipe(
        ofType(getCohortActions.updateActiveCohort.type),
        withLatestFrom(this.store.pipe(select(activeCohort))),
        exhaustMap(([action, cohort]) => this.cohortFeaturesServices.updateCohorts(action, cohort).pipe(

        )),
        map((response) => ({
            type: getCohortActions.updateActiveCohortSuccess.type, // success action
            success: response
        })),
        catchError((err) => of(getCohortActions.updateActiveCohortError(err))) // error action
    )
)
London804
  • 1,072
  • 1
  • 22
  • 47