NgRx 效果無限循環 (NgRx Effects infinite loop)


問題描述

NgRx 效果無限循環 (NgRx Effects infinite loop)

我知道這個問題在 SO 上已經被問了一百萬次了。但我需要幫助。我確實意識到我必須在這裡遺漏一些重要的東西。但我沒有看到它。

下面的代碼觸發了一個無限循環。REMOVE_PROJECT 僅被調度一次。REMOVE_PROJECT_SUCCESS 被無限觸發。'removed' 被無限記錄。我不知道為什麼。

所有動作都有唯一的類型。dispatch: false 為 REMOVE_PROJECT_SUCCESS 啟用。

操作:

export const REMOVE_PROJECT = createAction(
    '[Project] Remove Project',
    props<{ id: string }>()
);

export const REMOVE_PROJECT_SUCCESS = createAction(
    '[Project] Remove Project Success',
);

效果:

@Effect()
removeProject$ = createEffect(() => this.actions$.pipe(
    ofType(ProjectActions.REMOVE_PROJECT),
    switchMap(props =>
        this.projects.removeProject(props.id).pipe(
           map(() => ({ type: '[Project] Remove Project Success'}),
        // have also tried
        // map(() => ProjectActions.REMOVE_PROJECT_SUCCESS())
        )
    ))
))


@Effect({ dispatch: false })
removeProjectSuccess$ = createEffect(() => this.actions$.pipe(
    ofType(ProjectActions.REMOVE_PROJECT_SUCCESS),
    tap(() => console.log('removed')),
))

刪除功能:

removeProject(projectId): Observable<void> {
    return from(this.db.doc('projects/' + projectId).ref.delete());
}

參考解法

方法 1:

This is because you're using the @Effect() decorator with createEffect(). They both do the same thing under the hood, likely triggering the infinite loop. Remove EITHER the @Effect() annotations (recommended) or createEffect() (I'd leave this one).

To be more specific, the createEffect() also takes {dispatch: false} as the second argument (after your observable pipe). Since you don't include this option for the second one, it just re‑dispatches the actions you filtered with ofType, thereby firing the same actions over and over in the infinite loop you're experiencing.

Here's what the second effect should look like if you want to not dispatch:

removeProjectSuccess$ = createEffect(() => this.actions$.pipe(
    ofType(ProjectActions.REMOVE_PROJECT_SUCCESS),
    tap(() => console.log('removed')),
), { dispatch: false })

Under the hood, both the decorator and the function add annotations to the injectable class that the EffectsModule consumes. In this scenario, it makes an effect that will not dispatch, and a second one that dispatches by default. I hope this makes sense.

(by Friso Hoekstrawilsonhobbs)

參考文件

  1. NgRx Effects infinite loop (CC BY‑SA 2.5/3.0/4.0)

#ngrx-effects #ngrx #Angular #observable






相關問題

rxjs減少不繼續 (rxjs reduce does not continue)

從 reducer/action 觸發 API 重新加載的正確方法是什麼? (What's the proper way to trigger the API reload from reducer/action?)

Angular NgRx 效果,如何傳遞參數? (Angular NgRx effects, how to pass a parameter?)

NgRx 效果無限循環 (NgRx Effects infinite loop)

發送 forkjoin api,每個 api 之間有延遲 (Send forkjoin api with a delay in between each api)

如何從所有待處理的請求中取消特定請求 (How to cancel specific request from all pending request)

使用 NgRx 存儲優化 Angular 內存以避免內存洩漏 (Angular memory optimization with NgRx store to avoid memory leaks)

NgRx EffectsModule 導入組 (NgRx EffectsModule imports group)

切換地圖後在NGRX特效點擊功能中獲取動作道具 (Get action props in the NGRX effects tap function after switch Map)

如何防止在 NgRx 中第二次加載數據? (How prevent loading data second time in NgRx?)

需要幫助了解這種 Ngrx 效果 (Need help understanding this Ngrx effect)

測試效果 NgRx Angular 11 (Testing effects NgRx Angular 11)







留言討論