2017-02-12 4 views
1

の場合、私はngrx効果を使用するように移行していると私は、次の問題があります。dispatch戻りvoidので、私はエラーが私から発生した場合、ルータのナビゲーションを防ぐ方法がわかりませんngrx効果(例えば、this.userAccountService.updateFirstName(...から)。私のコンポーネントクラスからは、ルータのナビゲーションの防止効果の失敗/エラー

:私の効果クラスから

updateFirstName() { 
    this.formStatus.submitted = true; 
    if (this.formStatus.form.valid) { 
     //Dispatch from the store 
     this.store.dispatch(new UpdateFirstNameAction(this.formStatus.form.value.firstName)); 
     //Undesired behavior: will navigate even in case of error/failure! 
     this.router.navigate(['/dashboard/useraccount']); 
    } 
    } 

@Effect() 
    updateFirstName$: Observable<Action> = this.actions$ 
    .ofType(currentUserAccount.ActionTypes.UPDATE_FIRST_NAME) 
    .map((action: UpdateFirstNameAction) => action.payload) 
    .switchMap(firstName => 
     this.userAccountService 
     .updateFirstName(firstName) 
     .map(() => new UpdateFirstNameSuccessAction(firstName)) 
     //I obviously can't navigate from here 
    ); 

私はそれが良い練習(あるいは可能)であることを確認していないナビゲートするためにルータを使用しますその効果から。

私のエフェクトからエラーが発生した場合のルーターのナビゲーションを防ぐために、誰かがクリーンなソリューションを提案できますか?

+0

UpdateFirstNameSuccessActionはsetFirstNameSuccess = true、 になる必要があります。購読すると値を取得し、そうであればページにリダイレクトします。 –

+0

こんにちは@ShlomiLevi、私は新しい状態を導入するだろう。私はしませんか?一言で言えば、 – balteo

+0

の場合は、変更を保存する必要があります。 :) 新しい状態にする必要はありません。変更されたフィールドをサポートするように状態を構築するだけです。 これは、ストアに状態が必要であり、アクションをディスパッチするときに、基本的にストアを変更するためです。店舗を変更した後、変更されたフィールドに登録すると、それであなたはあなたが望むものに反応します:) –

答えて

1

@ngrx/router-storeモジュールを使用することをお勧めします。これによりルーティングアクションを作成することができ、それを使用していくつかのオプションがあります。

複数のアクションを1つのエフェクトから出力できます。あなたの成功アクションと(goアクションクリエータで作成した)ルーティングアクション:だからあなたの効果は二つの動作を発するようにconcatMapを使用することができ

import { go } from '@ngrx/router-store'; 
import 'rxjs/add/operator/concatMap'; 

@Effect() 
updateFirstName$: Observable<Action> = this.actions$ 
    .ofType(currentUserAccount.ActionTypes.UPDATE_FIRST_NAME) 
    .map((action: UpdateFirstNameAction) => action.payload) 
    .switchMap(firstName => this.userAccountService 
    .updateFirstName(firstName) 
    .concatMap(() => [ 
     new UpdateFirstNameSuccessAction(firstName), 
     go(['/dashboard/useraccount']) 
    ]) 
); 

はしかし、あなたはまた、唯一の管理別々の効果を使用して検討する必要がありますルーティング:

import { go } from '@ngrx/router-store'; 
import 'rxjs/add/operator/mapTo'; 

@Effect() 
updateFirstRouting$: Observable<Action> = this.actions$ 
    .ofType(currentUserAccount.ActionTypes.UPDATE_FIRST_NAME_SUCCESS) 
    .mapTo(go(['/dashboard/useraccount']); 

考慮すべきもう一つは、あなたがこのような何かを行うには、単純なアクション型・ツー・ルートマッピングのテーブルを使用することができるように、単一の効果は、複数のアクションに対応できるということです

いずれのオプションを選択しても、エフェクト内で開始されるナビゲーションのルーティングアクションを使用すると、テストが容易になります。エフェクトが特定のアクションを受け取ったときに、適切なアクションを確実に出すようにエフェクトテストを作成するのは簡単です。テスト効果に関する詳細はhereです。

+0

ありがとう、カートゥント。私は、ルーティングだけを管理する別々の効果がより好きです。私はまだ1つの質問を持っています:この解決策は 'ActionTypes.UPDATE_FIRST_NAME_SUCCESS'とルーティングの間の結合を導入しますか?このカップリングを避ける方法はありますか? – balteo

+1

特定のルートに移動するアクションが常に必要な場合、カップリングがどのように問題になるかはわかりません。あなたがナビゲートしたいと思うかもしれないし、したくない状況があるように思えます。私は別のオプションで答えを更新しました。エフェクトを保持するサービスを介してコンフィグレーションできるダイナミックテーブルを使用するように拡張することができます。したがって、UPDATE_FIRST_NAME_SUCCESSアクションをディスパッチする前に、アクションからルートへのマッピングを設定することができます。それのようなものは、あなたが探しているものに近いかもしれません。 – cartant

+0

ありがとうございます。最後の解決策は素晴らしく柔軟です。 – balteo

0

2つの方法で実行できます。

  1. 効果では、SUCCESSアクションをキャッチしてリダイレクトします。

    @Effect() someeffectの$:観察可能= this.actions $ .ofType(currentUserAccount.ActionTypes.UPDATE_FIRST_NAME_SUCCESS)
    .doという(アクション=>/* * /)action.payload(リダイレクトん)。購読して

のは、これはあなたの状態であるとしましょう: { アカウント:{ ユーザ名:ヌル } }

コンポーネント:

var username$ = this.store.select(account => account.username); 

username$.subscribe(user => { 
    // the user have changed due to reducer who is getting the action with new user. 
    // do here redirect... 
}); 
+0

ありがとう。しかしもう一つの質問:そこから 'select'ではなくstoreから' subscribe'する理由がありますか?また、コンポーネントからではなく、エフェクトからナビゲートするのがよい方法ですか? – balteo

+0

大歓迎です。はい、 'select'を使うべきです。それはあなたが店からスライスを得るからです。それはただ迅速で汚れた答えです;) あなたのBLだから効果からリダイレクトする方が良いです。あなたが選んだ効果を適用したり削除したりすることができます。場合によってはリダイレクトを行い、別の場合は他の操作を行います。あなたがしなければならないのは効果のダイナミックな適用/削除だけです。 –

関連する問題