How to get current value of State object with @ngrx/store?

后端 未结 10 1495
失恋的感觉
失恋的感觉 2020-12-08 06:13

My service class, before calling a web service, needs to get a property called dataForUpdate from my state. Currently, I\'m doing it like this:



        
相关标签:
10条回答
  • 2020-12-08 06:59

    I've created a minimalistic application that has a state with 2 counters which are properties of the AppState, and 2 reducers. Each reducer is bound to a particular counter, and I've subscribed an observable for each counter that will console.log its value. The reducers themselves also write to the console when called.

    There is a button which calls both reducers by dispatching an event. Also, the 2 counters are bound to 2 labels, so changes in them show - <p>Counter: {{counter1 | async}}</p>.

    Mapping each counter to a reducer is done with StoreModule.forRoot({ counter1: Reducer1, counter2 : Reducer2 })

    import { Component, NgModule } from '@angular/core';
    import { Store, Action, StoreModule } from '@ngrx/store';
    import { Observable } from 'rxjs/Observable';
    import { BrowserModule } from '@angular/platform-browser';
    
    interface AppState {
      counter1 : number;
      counter2 : number;
    }
    
    export function Reducer1(counter : number = 0, action : Action) {
      console.log(`Called Reducer1: counter=${counter}`);
      return counter + 1;
    }
    
    export function Reducer2(counter : number = 0, action : Action) {
      console.log(`Called Reducer2: counter=${counter}`);
      return counter + 2;
    }
    
    @Component({
      selector: 'app-root',
      template: `<p>Counter: {{counter1 | async}}</p>
      <p>Counter: {{counter2 | async}}</p>
      <button (click)='increment()'>Increment</button>`
    })
    export class AppComponent {
      title = 'app';
      counter1 : Observable<number>;
      counter2 : Observable<number>;
    
      constructor(private store : Store<AppState>) {
        this.counter1 = this.store.select('counter1');
        this.counter2 = this.store.select('counter2');
    
        this.counter1.subscribe(x => console.log(`Subscribe event for counter1 fired: counter=${x}`));
        this.counter2.subscribe(x => console.log(`Subscribe event for counter2 fired: counter=${x}`));
      }
    
      increment() {
        this.store.dispatch({type:'foo'});
      }
    }
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        StoreModule.forRoot({ counter1: Reducer1, counter2 : Reducer2 })
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    
    0 讨论(0)
  • 2020-12-08 07:00

    Extra comment. When I use this._store.value.StateReducer.currentPeriod.id

    Transpiler return "app/state/stateService.ts(133,35): error TS2339: Property 'StateReducer' does not exist on type 'AppState'."

    constructor ( public _store: Store<AppState>) {
    
        const store$ =  this._store.select ('StateReducer');
    
        .../...
    
    
        let saveTransaction = this.actions$
                      .filter (action => action.type==SAVE_TRANSACTION )
                      .map (action => { return { type:SAVING_TRANSACTION, payload : action.payload };  } )
                      .mergeMap ( action => this._transactionService.updateTransaction (
                                                                this._store.value.StateReducer.currentProfile.id, 
                                                                this._store.value.StateReducer.currentPeriod.id, 
                                                                action.payload),
                                    (state, webServiceResponse) =>  { return { type:TRANSACTION_UPDATED, payload :null  }; }) ;
    
    
    
    
    
    }
    

    To fix issue, I have changed BehaviorSubject.d.ts in rxjs\subject folder :

    import { Subject } from '../Subject';
    import { Subscriber } from '../Subscriber';
    import { Subscription } from '../Subscription';
    export declare class BehaviorSubject<T> extends Subject<T> {
        private _value;
        private _hasError;
        private _err;
        constructor(_value: T);
        getValue(): T;        
        value: T;             <=== I have changed it to value: any;
        _subscribe(subscriber: Subscriber<any>): Subscription<T>;
        _next(value: T): void;
        _error(err: any): void;
    }
    

    Not sure if it's a legit modification ;)

    0 讨论(0)
  • 2020-12-08 07:03

    this is work for me. i will get my object data.

    this.store.select('dataStore').subscribe(data => { 
              console.log(data)
     }
    
    0 讨论(0)
  • 2020-12-08 07:04

    Following the answer from @Sasxa, the syntax changed on newer versions of @nrgx/store (v5 and v6). After the underlying RxJS library was updated to ^5.5.0, there is now a pipe method available on all the Observable instances, which allows for easier chaining and changes how a subscription is achieved.

    So you can now do something like:

    import { take } from 'rxjs/operators';
    
    function getState(store: Store<State>): State {
       let state: State;
    
       store.select('your-state').pipe(take(1)).subscribe(
          s => state = s
       );
    
       return state;
    }
    

    Or, using strictly the pipe() operator:

    import { select } from '@ngrx/store';
    import { take } from 'rxjs/operators';
    
    function getState(store: Store<State>): State {
       let state: State;
    
       store.pipe(select('your-state'), take(1)).subscribe(
          s => state = s
       );
    
       return state;
    }
    

    And if you want to make your code a bit more readable you can also employ async/await mechanics like so:

    import { select } from '@ngrx/store';
    import { take } from 'rxjs/operators';
    
    function async getStateAsync(store: Store<State>): State {
       let state = await store
                 .pipe(
                    select('your-state'),
                    take(1)
                 )
                 .toPromise<State>();
    
       return state;
    }
    
    0 讨论(0)
提交回复
热议问题