Redux - Angular: How prevent actions called twice?

空扰寡人 提交于 2020-06-29 04:33:14

问题


Redux It's a very cool library, I really like it, but how can I prevent that actions call twice? What mistakes can generate this behavior ? Consider that I've already unsubscribe the subscription into the controller

constructor(private _store: Store<AppState>) {
    this.subscription = this._store.select('reduxObj').subscribe(function (item) {
      switch (item.type) {
        case fromAction.GETITEMS: {
          break;
        }
      }
    }.bind(this));
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }


  ngOnInit() {
    this._store.dispatch(new fromAction.GetListAction());
  }



    //REDUCER
    export function ReduxReducer(state: any = undefined, action: fromAction.actions) {

  switch (action.type) {
    case fromAction.GETITEMS: {
      return { ...state, type: fromAction.GETITEMS }
    }
  }


  //ACTION
  export class GetListAction implements Action {
    readonly type = GETITEMS;
    constructor() { }
  }

回答1:


People seem to focus on trivial things.

So I'll straight answer your question :

a select on a store listens to dispatch events in its most simple implementation.

You call dispatch twice, your subscription gets called twice.

Now this can change with effects and so on, but I'll assume you don't have any.

If it gets called twice, it's because your store is instantiated with a default value. In your reducers signature is

(state: MyState, action: MyAction implements Action) => any

And generally, you put it like this

myReducer(state: MyState = undefined, action: MyAction implements Action) { ... }

This means that you have your first value being undefined, and if you call dispatch, your second value is defined.

That's where the two calls come from.

And as a side note, you can leave it in the constructor, that won't change a damn thing.

EDIT

To ignore the first value, you can use filter or skip (not all at once, choose one depending on what you want) :

this.subscription = this._store.select('reduxObj').pipe(
  // For an array, will ignore all empty arrays
  filter(value => value.length),
  // For undefined, will ignore all falsy values
  filter(value => !!value),
  // Ignore first value only
  skip(1),
)



回答2:


First of all you don't need to .bind(this) to observer function. Secondly, you are able to take advantage from ES6 arrow functions instead of regular javascript functions as a callback (() => {}).

When it comes to your question - the best option to take only one value from Observable is adding take() stage to the RxJS pipe, like that:

         this.subscription = this._store.select('reduxObj')
           .pipe(take(1))
           .subscribe((item) => {
              switch (item.type) {    
                case fromAction.GETITEMS:{                                                                                                        
                  //...                                    
                  break;
                }
              }
        }); 

To use it you have to import take from 'rxjs/operators' assuming you're using RxJS 5.5 library or above.

import { take } from 'rxjs/operators';


来源:https://stackoverflow.com/questions/53298830/redux-angular-how-prevent-actions-called-twice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!