2017-11-16 6 views
1

私はそれに夢中になっていると伝えなければなりません。私はAngularFire2(v.5)でFirebaseからデータを取得しようとしていますが、@ ngrx/effectsでそれを扱い、@ ngrx/storeに保存しています。その後、firefbaseからArrayFire2(v5)とngrxエフェクトを使用してリストを取得する

spaces.effects.ts

@Effect() 
    getSpaces$ = this.actions$.ofType(SpacesActions.GET_SPACES_REQUEST) 
    .switchMap((action: SpacesActions.GetSpacesRequest) => { 
    return this.afs.list<Space>('/spaces').snapshotChanges() 
     .switchMap(actions => { 
     console.log('action is ', actions); 
     return actions.map(space => { 
     const $key = space.payload.key; 
     const data: Space = { $key, ...space.payload.val() }; 
     console.log('snapshot is: ', data); 
     return new SpacesActions.GetSpacesSuccess(data); 
     }); 
    } 
); 

私の「アクション」データとキーが付属しています:私は、キーを使用してデータを必要とするだけでなく、効果の私のコードは次のようになりますアイテムを簡単に更新したり削除したりできるので、各アイテムのキーを取得できます。私のデータベースには3つのキーがある3つのアイテムがあります。このコードを実行してログに記録すると、最初はペイロードで1つの配列のすべての項目が表示され、2番目のログでは各ペイロードがスナップショットとして表示されます。

私がGetSpacesSuccessを呼び出すと、私が(キーとアイテムで)取得したすべてのスナップショットを送信して保存したいと思います。私がやっているやり方は、今度はこのアクションを3回派遣し、最初のものが第2のものによって上書きされるので、画面上に2つのアイテムしか見ることができません。

したがって、2つの質問:キーを使ってfirebaseからアイテムを取得し、@ngrxでそれらを保存する簡単な方法はありますか?そうでなければ、最初のアイテムがオーバーライドされ、アクションが3回ディスパッチされている間違ったことは何ですか?

私が学んでいるように、私はそれに最善を尽くしています。ありがとうございました!

spaces.reducers.ts

case SpacesActions.GET_SPACES_REQUEST: 
    return { 
     state, 
     spaces: null, 
     loading: true 
    }; 
    case SpacesActions.GET_SPACES_SUCCESS: 
    return { 
     ...state, 
     ...action.payload, 
     spaces: [state, action.payload], 
     loading: false 
    }; 

spaces.actions.ts

export class GetSpacesRequest implements Action { 
    readonly type = GET_SPACES_REQUEST; 

} 

export class GetSpacesSuccess implements Action { 
    readonly type = GET_SPACES_SUCCESS; 

    constructor(public payload: Space) {} <<<<<HERE I'D LIKE TO GET THE FULL ARRAY WITH EACH KEY 
} 

答えて

0

私が正しくあなたの質問を理解している場合、あなたはまた、そのを格納し、各項目の保存したいですキー。あなたはMapを探しています。

私はあなたの特徴を次のように構成します。

spaces.actions.ts

ローディングスペース成功はスペースの唯一の配列を有している、何のペイロードを必要としません。私はあなたの減速機(stringがあなたの鍵である)にあなたのMap<string,Space>を構築すべきだと思います。

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

/** App Models **/ 
import { Space } from './space.model'; 

export const GET_SPACES = '[Spaces] Spaces get'; 
export const GET_SPACES_SUCCESS = '[Start] Spaces get - Success'; 

export class GetSpacesAction implements Action { 
    readonly type = GET_SPACES; 
} 

export class GetSpacesActionSuccess implements Action { 
    readonly type = GET_SPACES_SUCCESS; 
    constructor(public payload: Space[]) {} 
} 

export type All 
    = GetSpacesAction 
    | GetSpacesActionSuccess; 

spaces.effects.ts

私はあなただけのスペースをフェッチする方法を必要とすると仮定しています。他のことをする必要がある場合は、このコードを編集してください。 spaceService.getSpaces()は、Spacesの配列だけを返すものとします。したがって、新しいSpaceモデルを作成し、サービスで、各jsonエントリをnew Space()にマッピングします。ここで

import { Injectable } from '@angular/core'; 
import { Actions, Effect } from '@ngrx/effects'; 

/** rxjs **/ 
import {map} from 'rxjs/operators/map'; 
import {mergeMap} from 'rxjs/operators/mergeMap'; 
import {catchError} from 'rxjs/operators/catchError'; 

/** ngrx **/ 
import * as spacesActions from './spaces.actions'; 

/** App Services **/ 
import { SpacesService } from './spaces.service'; 

@Injectable() 
export class SpacesEffects { 

    @Effect() getSpaces$ = this.actions$ 
     .ofType(spaceActions.GET_SPACES) 
     .pipe(
      mergeMap(() => { 
      return this.spaceService.getSpaces() 
       .pipe(
       map((spaces) => { 
        return new spacesActions.GetSpacesActionSuccess(spaces); 
       }), 
       catchError((error: Error) => { 
        // Handle erro here 
       }) 
      ); 
      }) 
     ) 
    ; 

    constructor(private spacesService: SpacesService, private actions$: Actions) { } 

} 

spaces.reducer.ts

あなたのマップを構築し、あなたはまた、例えば、そのキー与えられたスペースを返すために新しいアクションを作成することができます。私はあなたがここで任意のローディングパラメータが必要だと思う、私はあなたのビューでいくつかの読み込み処理のためにそれを使用していると思う、ちょうどAsyncPipeあなたのビューで使用して、*ngIf空白があるかどうかをチェックして読み込みアニメーションを処理します。

/** ngrx **/ 
import {createFeatureSelector} from '@ngrx/store'; 
import {createSelector} from '@ngrx/store'; 
import * as spacesActions from './spaces.actions'; 

export type Action = spacesActions.All; 

/** App Models **/ 
import { Space } from './space.model'; 

export interface SpaceState { 
    keySpaces: Map<string, Space>; 
    spaces: Space[]; 
    keys: string[]; 
} 

export const initialState: SpaceState = { 
    keySpaces: new Map<string, Space>(), 
    spaces: [], 
    keys: [] 
}; 

// Selectors 
export const selectSpace = createFeatureSelector<SpaceState>('space'); 
export const getKeySpaces = createSelector(selectSpace, (state: StartState) => { 
    return state.keySpaces; 
}); 
export const getSpaces = createSelector(selectSpace, (state: SpaceState) => { 
    return state.spaces; 
}); 
export const getKeys = createSelector(selectSpace, (state: SpaceState) => { 
    return state.keys; 
}); 

export function spacesReducer(state: SpaceState = initialState, action: Action): SpaceState { 
    switch (action.type) { 
     case startActions.GET_SPACES_SUCCESS: 
      // Since we return this from effect 
      const fetchedSpaces = action.payload; 
      const fetchedKeys = []; 
      const keySpacesMap = new Map<string, Space>(); 
      fetchedSpaces.forEach((space: Space) => { 
       fetchedkeys = fetchedKeys.concat(space.key); 
       keySpacesMap.set(space.key, new Space(space)); 
      } 
      returns { 
       ...state, 
       keySpaces: keySpacesMap, 
       spaces: fetchedSpaces, 
       keys: fetchedkeys 
      } 
     default: { 
      return state; 
     } 
    } 
} 

そして、最後に、あなたのようなあなたのコンポーネントで、このようなパラメータを得ることができる必要があります:もちろん

. . . 

keySpaces$ = Observable<Map<string, Space>>; 
spaces$ = Observable<Array<Space>>; 
keys$ = Observable<Array<string>>; 

constructor(private _store: Store<AppState>) { 
    this.keySpaces$ = this._store.select(getKeySpaces); 
    this.space$s = this._store.select(getSpaces); 
    this.keys$ = this._store.select(getKeys); 
} 

. . . 

ngOnInit() { 
    this._store.dispatch(new spacesActions.GetSpacesAction); 
} 

. . . 

AppStateに新しい状態を追加します。

. . . 

export interface AppState { 
    . . . 
    space: SpaceState; 
} 
1

AndreaM16 @おかげで最も完全な答え。私はそれに取り組んで夜を過ごし、私は違ったことをやった。実際、学習過程で私たちは知識を得るために間違いを犯します。おそらくあなたのソリューションは私のものより優れていると私はそれを勉強します、ありがとう。可能であれば、私のソリューションに関するご意見をお聞きしたいと思います。

private spacesList = 'spaces/'; 
@Effect() 
    getSpaces$ = this.actions$.ofType(SpacesActions.GET_SPACES_REQUEST) 
    .switchMap(payload => this.afs.list(this.spacesList).snapshotChanges() 
    .map(spaces => { 
     return spaces.map(
      res => { 
      const $key = res.payload.key; 
      const space: Space = {$key, ...res.payload.val()}; 
      return space; 
      } 
    ); 
    }) 
    .map(res => 
     new SpacesActions.GetSpacesSuccess(res) 
    )); 

リデューサー

case SpacesActions.GET_SPACES_REQUEST: 
    return Object.assign({}, state, { 
     spaces: null, 
     loading: true 
    }); 
    case SpacesActions.GET_SPACES_SUCCESS: 
    return Object.assign({}, state, { 
     spaces: action.payload, 
     loading: false 
    }); 

アクション

最後に

、文書の多くを読んだ後、私の効果は、私もエラーキャッチャーを持っていない、今、この1であります

export class GetSpacesRequest implements Action { 
    readonly type = GET_SPACES_REQUEST; 

} 

export class GetSpacesSuccess implements Action { 
    readonly type = GET_SPACES_SUCCESS; 

    constructor(public payload: Space[]) {} 
} 

そして、私のコンポーネントでは、リストが必要です:

constructor(private store: Store<fromSpaces.FeatureState>) {} 
ngOnInit() { 
    this.store.dispatch(new SpacesActions.GetSpacesRequest()); 
    this.spacesState = this.store.select('spaces'); 
} 
+1

私はあなたを助けました。ここでのいくつかの点は、ツリーの振る舞いによってバンドルのサイズが大幅に縮小されるので、 'pipe'を使って' rxjs'を扱って、 '効果'を変更します。 [この記事で](https://blog.angularindepth.com/rxjs-understanding-lettable-operators-fe74dda186d3?gi=3218b91fbbac)をご覧ください。一般的に、 '効果'では、単にいくつかのサービスを呼び出し、成功アクションやいくつかのデータを返す他のアクションを出す一方で、「還元プロセス」では、必要なものを返すためにそのデータを再生します。 yoyur 'store.select(...)'をコンストラクタに移動します。 – AndreaM16

+0

[ngrx-platform sample app](https://github.com/ngrx/platform/tree/master/example-app)に従ってください。 – AndreaM16

+0

あなたのポイントを得ました。私はそれらを適用しました。あなたのコメントをありがとう。 –

関連する問題