angular - NgRx Hämta värde utan att prenumerera
Jag arbetar mig igenom några ngrx-handledningar och jag tror att jag börjar få min hjärna att förstå det.
Det jag inte förstår är hur man gör något så enkelt som att få ett värde från Store:
Mål: Hämta ett värde från butiken utan att behöva subscribe till det. T.ex.: store.myStoreProperty eller store.getValue(<selector>) eller ?
Såvitt jag förstår är det enda sättet att hämta ett värde från lagret att göra något sådant här:
private readonly _store: Store<ApplicationState>;
// ...
this._store.select(state => state.currentUser).subscribe(user => {
if (!user) { return; }
// ...
});
Fråga: Finns det något sätt att ">omedelbart" få ett värde från butiken utan att behöva prenumerera?
Jag kanske bara har svårt att fatta selectors, men jag trodde typ att det var vad de var till för. Exempel från dokumentationen:
import { createSelector } from '@ngrx/store';
export interface FeatureState {
counter: number;
}
export interface AppState {
feature: FeatureState;
}
export const selectFeature = (state: AppState) => state.feature;
export const selectFeatureCount = createSelector(
selectFeature,
(state: FeatureState) => state.counter
);
I det här exemplet tänkte jag att jag bara kunde kalla selectFeature eller skicka den till this._store.select(selectFeature) för att få det faktiska värdet, men det returnerar ett observable (och vill alltså att du ska prenumerera på det).
Mitt huvudsakliga användningsfall här är att jag vill komma åt aktuell användarinformation genom hela livscykeln för min app. Jag har en effect som hämtar den informationen från servern, och allt fungerar jättebra. Dock är jag lite förvirrad över hur jag enkelt kan komma åt värdet från store utan att behöva strö .subscribe överallt.
Och ja, jag har sett detta men det hjälper mig inte.
Svar #1
Vad sägs om att du lägger till din egen prenumerationsfunktion och kallar på den varje gång?
getValue(obj: Observable<any>){
let value: any;
obj.subscribe(v => value = v);
return value;
}
showme(){
console.log(this.getValue(this.user$)); // single value => works
console.log(this.getValue(this.projects$)); // array => works
}
Observera att du förlorar magin med observables, så när värdet ändras kommer det inte att uppdatera ditt frontend etc... Du kommer bara att ha värdet vid det ögonblick i tiden när du frågar efter värdet.
referens till stackblitz-demo
Sättet du kallar dina selectors på verkar fel, du borde importera dem på detta sätt:
import * as fromAuth from '../../auth/state/reducers';
import * as fromData from '../../data/state/reducers';
Och du bygger din konstruktor så här:
constructor(private store: Store<fromAuth.State & fromData.State>) {
Din select skulle då kunna se ut så här,
this.user$ = store.pipe(select(fromAuth.getUser));
let user = this.getValue(store.pipe(select(fromAuth.getUser))); // this would get you the current user value
Kolla in ngrx-exempelappen, speciellt den här indexsidan som jag hänvisar till, för att kolla på selectors. Kolla in detta exempel på hur de använder selectors och importerar staten
Normalt bygger du containrar och komponenter. Du bygger en container som är ansvarig för att hämta data från lagret, som du sedan skickar med den asynkrona pipen till nästa container eller komponent som är ansvarig för visningen. Med ngOnChanges kan du upptäcka förändringar och uppdatera frontend därefter.
Svar #2
Du kan använda async-pipe på detta sätt
export class MyComponent implements OnInit {
data$: Observable<any>;
constructor(private store: Store<ApplicationState>) {}
ngOnInit() {
this.data$ = this.store.pipe(select(yourSelector));
}
}
Då i din åsikt
<app-data [data]="data$ | async"></app-data>
