0
votes

I have this ngrx effect that is calling in this example to movies service, but is depending of a value selector, if this values is as expected in validation, the effect sould send a new action, this way I avoid to call the service because the condition. Right now I cannot use another action (this would be more descriptive) in the if block because of this error:

Type 'Observable' is not assignable to type 'Observable | ((...args: any[]) => Observable)'.

Type 'Observable' is not assignable to type 'Observable'.ts(2322).

What is the better way to handle this scenario?

loadMovies$ = createEffect(() => this.actions$.pipe(
        ofType('[Movies Page] Load Movies'),
        concatMap(action => of(action).pipe(withLatestFrom(this.store.select(getBlockBuster)))),
        mergeMap(([{payload}, foundBlockBuster]) => {
            if (!foundBlockBuster) {
                // in order to avoid errors we need to use this({ type: '[Movies API] Movies Loaded Success', payload: movies }))
                return of({ type: '[Movies] The block busters are rent' })
            }
            return this.moviesService.getAll()
                .pipe(
                    map(movies => ({ type: '[Movies API] Movies Loaded Success', payload: movies })),
                    catchError(() => of({ type: '[Movies API] Movies Loaded Error' }))
                )
            })
        )
    );
1

1 Answers

0
votes

This error is happening because you should return Observable<action> instead your code is returning two types of object literal (assumed as it is of type Action) one which has only type property and another one has type and payload. To fix this error have an array of Action and then push your object literal in that array and then return that array like this:

loadMovies$ = createEffect(() => this.actions$.pipe(
        ofType('[Movies Page] Load Movies'),
        concatMap(action => of(action).pipe(withLatestFrom(this.store.select(getBlockBuster)))),
        mergeMap(([{payload}, foundBlockBuster]) => {

            const actions = new Array<Action>();

            if (!foundBlockBuster) {
                actions.push({ type: '[Movies] The block busters are rent' });
                return actions;                
            }
            return this.moviesService.getAll()
                .pipe(
                    mergeMap(movies => {
                      actions.push({ type: '[Movies API] Movies Loaded Success', payload: movies });
                      return actions;
                    }),
                    catchError(() => {
                      actions.push({ type: '[Movies API] Movies Loaded Error' });
                      return actions;
                    })
                )
            })
        )
    );

Alternatively, you can typecast your object literals as <Action> like this:

<Action>{ type: '[Movies] The block busters are rent' }

But I prefer to use the array as array allows to dispatch multiple actions if my app logic needs so.

Hope it helps.