redux - 在效果失败/错误的情况下防止路由器导航

标签 redux rxjs rxjs5 ngrx ngrx-effects

我正在迁移到使用 ngrx Effects,但遇到以下问题:由于 dispatch 返回 void 我不确定如何阻止路由器导航如果我的 ngrx 效果发生错误(例如,来自 this.userAccountService.updateFirstName(...)。

来 self 的组件类:

  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']);
    }
  }

来 self 的效果类:

  @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
    );

我不确定使用路由器从效果中导航是否是一个好的做法(甚至可能)。

有人可以建议一个干净的解决方案来防止路由器导航在我的影响下发生错误吗?

最佳答案

我建议使用@ngrx/router-store模块。使用它,您可以创建路由操作,并且使用它,您有一些选择。

您可以从一个效果发出多个 Action 。因此,您的效果可以使用 concatMap 发出两个操作:成功操作和路由操作(使用 go 操作创建者创建):

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']);

要考虑的另一件事是单个效果可以响应多个操作,因此您可以使用简单的操作类型到路由映射表来执行如下操作:

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

simpleRoutes: { [type: string]: string } = {
  [currentUserAccount.ActionTypes.UPDATE_FIRST_NAME_SUCCESS]: '/dashboard/useraccount'
};

@Effect()
simpleRouting$: Observable<Action> = this.actions$
  .map((action) => this.simpleRoutes[action.type])
  .filter(Boolean)
  .map((route) => go([route]));

无论您选择哪个选项,使用在效果内启动的路由操作进行导航都可以使事情更容易测试。编写效果测试很容易,以确保当效果接收到特定操作时,它会发出适当的操作。更多测试效果信息here .

关于redux - 在效果失败/错误的情况下防止路由器导航,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42189538/

相关文章:

redux 状态树具有非常大的(实际上与状态无关)数据结构

reactjs - 从 hashHistory React-router-redux 中删除 queryKey

angular - Angular 变化检测是否发生在服务中?

angular - "RxJS could not find any global context"

angular - Response.json() 使用接口(interface)绑定(bind)到单个对象 - RxJs/Observable 失败

javascript - 如何更改 RxJS 使用的默认调度程序?

javascript - 使用 props.change 更改 redux-form 中输入字段的值

javascript - 尝试使用容器的 props 映射 Redux 状态时遇到困难

javascript - 类型 'subscribe' 上不存在属性 'Promise'

angular - 一个 @ngrx/effect 中的多个 Http 调用