zangarmarsh
zangarmarsh

Reputation: 349

Angular NgRx's Effect creates an infinite loop

first of all it is worth mentioning the fact that I still haven't very clear rxjs's operators. I studied them but in the practical act if I either use switchMap, mergeMap or map the result still seems the same.

The code below creates an infinite loop, I tried to place debuggers strategically in order to understand the flow but it must be strictly related to the HTTP response time, hence appears to jump between the effects in a very random way.

@Effect()
addNewDocument = this.actions$.pipe(
    ofType(UserActions.ADD_DOCUMENT),
    map((action: UserActions.AddNewDocument) => {
        return action.document;
    }),
    switchMap((document: FormData) => {
        return this.store.select('user').pipe(
            map((user) => {
                return {
                    document,
                    uuid: user.uuid
                };
            })
        );
    }),
    switchMap((payload: { document: FormData, uuid: string }) => {
        return this.httpClient.post(
            `${environment.apiUrl}user/${payload.uuid}/documents`,
            payload.document
        ).pipe(
            mergeMap((response: any) => {
                return [
                    {
                        type: UserActions.ADDED_DOCUMENT,
                        response
                    }
                ];
            }),
            catchError((error) => of(new AppActions.GenericError(error)))
        );
    })
);

@Effect({dispatch: false})
addedNewDocument = this.actions$.pipe(
    ofType(UserActions.ADDED_DOCUMENT),
    tap(() => {
        this.router.navigate(['/user/documents']);
    })
);

My intent is:

  1. Intercept UserActions.ADD_DOCUMENT action
  2. keep track of the uuid for the http request
  3. Make the request and handle the response through the event UserActions.ADDED_DOCUMENT in order to update the state through its reducer

I'd really appreciate if you help me to understand what's wrong. If you think I missused some operators or you know a better method to use them, please let me know.

Thank you in advance.

Upvotes: 2

Views: 1381

Answers (1)

user2216584
user2216584

Reputation: 5602

It appears that your user state is changing in your application which is causing the looping in the effect. Try using take(1) while taking user state in effect like this:

switchMap((document: FormData) => {
        return this.store.select('user').pipe(
            take(1),
            map((user) => {
                return {
                    document,
                    uuid: user.uuid
                };
            })
        );
    })

take(1) will complete the observable and will tear down the action until the next UserActions.ADD_DOCUMENT action dispatched. Hope it helps.

Upvotes: 1

Related Questions