Infinite loop with ngrx/effects

2019-07-28 04:51发布

问题:

I'm trying to understand ngrx/effects. I have built a simple function that increments number by 1 with each click. But it's going in an infinite loop when clicked, not sure whats going on. I'm sure im making some stupid mistake.

monitor.effects.ts

@Injectable()
export class MonitorEffects {
    @Effect()
    compute$: Observable<Action> = this.actions$
        .ofType(monitor.ActionTypes.INCREMENT)
        .map((action: monitor.IncrementAction) => action.payload)
        .switchMap(payload => {
            return this.http.get('https://jsonplaceholder.typicode.com/users')
             .map(data => new monitor.IncrementAction(payload+1))
             .catch(err => of(new monitor.InitialAction(0)))
        });

    constructor(private actions$: Actions, private http:Http ) {};
}

monitor.component.ts

ngOnInit() {
    this.storeSubsciber = this
      .store
      .select('monitor')
      .subscribe((data: IMonitor.State) => {
        this.value = data.value;
        this.errorMsg = data.error;
        this.currentState = data.currentState;
      });
  }

  increment(value: number) {
    this.store.dispatch(new monitorActions.IncrementAction(value));
  }

monitor.reducer.ts

export const monitorReducer: ActionReducer<IMonitor.State> = (state = initialState, action: Actions) => {
  switch (action.type) {
    case ActionTypes.INCREMENT:
      return Object.assign({}, { value: action.payload, currentState: ActionTypes.INCREMENT, error: null });
...
...
...

    default:
      return Object.assign({}, { value: 0, currentState: ActionTypes.INITIAL, error: null });
  }
}

回答1:

An Effect allows you watch a given action type and react to that action every time it's been dispatched.

So if you watch actions X in some effect and dispatch from that effect another action X, you'll end up in an infinite loop.

In your case : Your action is of type .ofType(monitor.ActionTypes.INCREMENT) and from your effect you then dispatch an action monitor.ActionTypes.INCREMENT (from this part I assume : monitor.IncrementAction(payload+1)), then the effect is triggered again, and again, and again, ...



回答2:

I had this same issue, and the answer was that my effect didn't return a completely different action from the one that the current effect was keying on.

For my affect, I only did a .do(), and didn't switchMap it to a new action. That was my issue. Because I didn't need to fire a new action, I made a NoopAction that get returns. It is implying that no one should ever use the NoopAction in a reducer.