问题
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