2016-02-25 149 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 { } 
相关问题