2016-02-25 158 views
23

我的服務類在調用Web服務之前需要從我的狀態獲取名爲dataForUpdate的屬性。目前,我正在做這樣的:如何使用@ ngrx/store獲取State對象的當前值?

constructor (public _store: Store<AppState>, 
       public _APIService:APIService) { 

    const store$ = this._store.select ('StateReducer'); 

    .../... 

    let update = this.actions$.filter (action => action.type==UPDATE) 
           .do((action) => this._store.dispatch({type: REDUCER_UPDATING, payload : action.payload })) 
     *** GET STATE ***==> .mergeMap (action => store$.map ((state : AppState)=> state.dataForUpdate).distinctUntilChanged(), 
             (action, dataForUpdate) { 
                return { type:action.type, payload : {employee:action.payload, dataForUpdate :dataForUpdate } }; 
                  }) 
     * AND CALL API *==> .mergeMap (action =>this._APIService.updateEmployee(action.payload.employee, action.payload.dataForUpdate), 
             (action, APIResult) => { return { type:REDUCER_UPDATED }}) 
           .share(); 


    .../... 

    let all = Observable.merge (update, ....); 
    all.subscribe ((action:Action) => this._store.dispatch (action)); 

} 

我使用angular2店 - 例如(https://github.com/ngrx/angular2-store-example/blob/master/src/app/users/models/users.ts)爲指導,以跟隨。

我想知道是否存在更好(更清潔)的方式?

活生生的例子:對@ NGRX /存儲1.x版https://plnkr.co/edit/WRPfMzPolQsYNGzBUS1g?p=preview

回答

38

原來的答覆

@ngrx/store擴展BehaviorSubject,它有一個value屬性,你可以使用。

this._store.value 

,這將是您的應用程序的當前狀態,並從那裏你可以選擇屬性,過濾器,地圖等等

更新:

我花了一段時間來圖什麼是什麼在你的榜樣(:要獲得dataForUpdate電流值,你可以使用:

let x = this._store.value.StateReducer.dataForUpdate; 
console.log(x); // => { key: "123" } 

更新@ NGRX /存儲用於同步拉最近的狀態值了商店已被刪除

這些API:V2.X

隨着更新到2.0版本,如docs描述value被刪除。取而代之的是,你總是可以依靠subscribe()同步運行,如果你必須得到狀態值:

function getState(store: Store<State>): State { 
    let state: State; 

    store.take(1).subscribe(s => state = s); 

    return state; 
} 
+0

那麼容易做到。例如:this._store.value.StateReducer.dataForUpdate –

+0

你讓它變得有點複雜了(: – Sasxa

+0

我同意!爲什麼我的感覺是更簡單的解決方案必須存在,謝謝你的幫助 –

0

額外的評論。當我使用this._store.value.StateReducer.currentPeriod.id

傳輸器返回「app/state/stateService.ts(133,35):錯誤TS2339:屬性'StateReducer'在類型'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 }; }) ; 





} 

要解決的問題,我已經改變了BehaviorSubject.d.ts在rxjs \文件夾主題:

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; 
} 

不知道這是否是一個合法的修改;)

+1

更多「合法」將是構造函數(公共_store:商店)'(: – Sasxa

3

withLatestFrom()combineLatest()方法訂閱鏈給你正是你需要的,並且符合Observables + Ngrx的精神。

在上面的代碼的地方得到國家.mergeMap(),採用withLatestFrom()會是這個樣子:

... 
.withLatestFrom(store$, (payload, state) => { 
    return {payload: payload, stateData: state.data} 
}) 
... 

順便說一句,在原來問題的代碼似乎是管理終極版動作異步效果,這正是ngrx/effects庫的用途。我建議你檢查一下。在將Effects連接起來之後,用於管理異步Redux操作的代碼更清晰。 Jim Lynch撰寫的這篇文章對我也很有幫助:The Basics of "ngrx/effects", @Effect, and Async Middleware for "ngrx/store" in Angular 2

1

不嚴格地直接回答這個問題,但是我發現這個頁面正在尋找如何從商店檢索單個值。

爲了實現這一點,可以從注入的@ngrx/store對象State如下所示:

import { State } from '@ngrx/store'; 

constructor (private state: State<AppState>) { 
    let propertyValue = state.getValue().path.to.state.property; 
} 

state對象保存在一個私人_value屬性的當前狀態,通過.getValue()方法來訪問。

+0

它應該請注意,在撰寫本文時(@ngrx v4.1.1),在與Redux DevTools一起使用時注入'State'會導致問題,**重複發送的每個動作**。儘管更多,但可能並非最實用的路由簡潔。 –

0

我創建了一個具有2個計數器的狀態的簡約應用程序,這兩個計數器屬於AppState和2個reducer。每個reducer都綁定到一個特定的計數器,並且我已爲每個計數器訂閱了一個可觀察值,其值將爲console.log。調用者本身也會在調用時寫入控制檯。

有一個按鈕通過調度一個事件來調用兩個reducer。另外,2個計數器綁定到2個標籤,所以其中的更改顯示 - <p>Counter: {{counter1 | async}}</p>。 )除了它看來,我必須包括減速機的名稱;

映射每個櫃檯的減速與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 { } 
相關問題