store
store copied to clipboard
How to get @select to return an Observable instead of AnonymousSubject?
At the moment the @select returns an AnonymousSubject which is breaking the CanLoad and Resolve routing guards in Angular 4 (or 2 and above). It seems just these two router guards cannot handle it as the CanActivate deals with AnonymousSubject without an issue.
Is there any way that I can force it to return an Observable or even a 'normal' Subject?
Thank you
If you have your CanLoad use ngRedux.select(.....) are you getting the same issue, just wondering if this is applying to just the decorator, or select in general.
It happens when using the @select as well as ngRedux.select(.....).
I did a bit of investigating with the hope of submitting a PR. However, being from a Java background and being relatively new to JS/TS world, I don't know much of RX to be able to resolve this.
This happens as soon as any operator (filter / distinctUntilChanged / etc) is applied to the this._store$ variable (which is meant to be a BehaviorSubject) in the src/components/ng-redux.ts.
this._store$ = new BehaviorSubject<RootState>(null)
.filter(n => n !== null)
.switchMap(n => {
return Observable.from(n as any);
}) as BehaviorSubject<RootState>;
Although it's casted to a BehaviorSubject, it still get assigned as an AnonymousSubject.
The returned Observable also get changed to an AnonymousSubject when the this._store$.distinctUntilChanged is applied from the select<S>(...) method.
Hopefully, that will give some indication to what's happening and appreciate your help.
Thanks Yohan
Still looking into this, thanks for the insight.
In the route guard, could you do something like:
ngRedux.select('selector').asObservable(); // hides the subject, converts to observable
If that works out, I'll see if it's possible to update select to return the Observable<T> without introducing any breaking changes.
It didn't work :(
I couldn't directly use asObservable() and had to cast to a Subject and then use asObservable().
(<Subject<any>>this.ngRedux.select<any>('selector')).asObservable();
I think the fact that there is an AnonymousSubject in the observer chain is causing it to break. Do you think it's a bug in the @angular/router / Resolve?
Another suggestion: if we bring the operators individually rather than hoping Webpack/SystemJS import the correct operators, do you think it might resolve the issue? I have a feeling when the filter, switchMap and the distinctUntilChanged are applied to the ngRedux store it's importing operators that generate AnonymousSubject rather than a simple Subject which is the root cause of this problem - I may be wrong.
import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/distinctUntilChanged';
Until there is a permanent fix, I am returning a Promise and within that subscribing to the store and only resolving the Promise when expected data arrive - a workaround :).
I know @SethDavenport has done quite a bit of refactoring of the guts of NgRedux - wondering if this is still an issue with the newer releases?
Concerning Angular router and redux with @select I posted an issue here: https://github.com/angular/angular/issues/18991
Does @select complete?
Any updates on this? I need to .concatMap Observables with the @select decorator, but it's not possible because @select always return an AnonymousSubject.
@markusfalk @lvidal1 observables returned from @select and .select will not complete - they are Observable slices of state that remain active.
If you need to use them in a context where they need to 'complete' - such as in a resolver, route guard, etc - using an operator like .first() or .take() will get the current value and complete the observable.
Facing the same issue. Gone through the comments however didn't get the proper solution.
Can anyone help how to get the normal object while using @select?
Is there any update on this issue?