【问题标题】:ngrx routing when action is dispatched调度操作时的ngrx路由
【发布时间】:2017-03-13 10:08:47
【问题描述】:

我正在使用 ngrx 来存储我的用户状态。对于用户状态,我的意思是具有一些用户属性的 IUser 类对象。

我设置了几个操作 ('USER_LOGIN', 'USER_LOGIN_SUCCESS' and 'USER_LOGJN_FAILED')。

目前,当一个USER_LOGIN_SUCCESS 被调度时,reducer 将新的用户信息分配给我的IStore.user ngrx 存储字段。当它改变时:

this.user$ = this.store$.select(state => state.user);
this.userSub = this.user$.subscribe(
    (user: IUser) => {
        if (user.id != null)
           this.router.navigate(['/app']);
    }
);

如您所见,我只检查更改后用户的状态是否为user.id != null,然后导航到/app 路由。

有没有使用更优雅的方式来做到这一点。例如,

  1. 没有显式订阅我的IStore.user 字段?
  2. 我能否在调度操作 ('USER_LOGIN_SUCCESS') 时直接导航到路线?
  3. 我能否将所有这些行为集中在一个注射剂中?

有什么想法吗?

【问题讨论】:

    标签: angular ngrx


    【解决方案1】:

    是的,你可以用更优雅的方式做到这一点。
    让我们一步一步地回顾它:)

    1) 使用 rxjs 中的 filter 而不是 if 语句

    this.userSub = this
      .user$
      .filter((user: IUser) => user.id !== null)
      .subscribe((user: IUser) => this.router.navigate(['/app']));
    

    2) 避免逐个处理订阅
    (Ben Lesh 在Medium 上发表了一篇很棒的文章)

    private componentDestroyed$: new Subject<void>();
    
    ngOnInit() {
      this
        .user$
        .filter((user: IUser) => user.id !== null)
        .takeUntil(this.componentDestroyed$)
        .subscribe(_ => this.router.navigate(['/app']));
    }
    
    ngOnDestroy() {
      this.componentDestroyed$.next();
      this.componentDestroyed$.complete();
    }
    

    3) 不要在subscribe中应用你的逻辑

    在订阅之前使用domap 处理您的逻辑。
    - do 如果您只是需要做某事
    - map如果你想返回结果

    this
      .user$
      .filter((user: IUser) => user.id !== null)
      .takeUntil(this.componentDestroyed$)
      .do(_ => this.router.navigate(['/app']))
      .subscribe();
    

    (CF 下一部分“为什么”)

    4) 如果您想重用或导出某些逻辑,请使用“选择器”

    如果我必须对您的代码进行一些猜测,我想您的 user$ 是当前用户。那个连接对吗?而且您可能必须将所有代码复制到应用的其他部分才能再次找到该用户。

    这是“selector”的一个很好的用例。
    (我在这里导出了 2 个函数,所以这段代码可以对 AOT 友好)。 p>

    export function _getCurrentUser(store: Store<any>) {
      return store$
        .select(state => state.user)
        .filter((user: IUser) => user.id !== null);
    }
    

    然后在你的组件中:

    this
      .store$
      .let(getCurrentUser)
      .takeUntil(this.componentDestroyed$)
      .do(_ => this.router.navigate(['/app']))
      .subscribe();
    

    我们终于有了

    user.selector.ts

    export function getCurrentUser(store: Store<any>) {
      return store$
        .select(state => state.user)
        .filter((user: IUser) => user.id !== null);
    }
    

    component

    private componentDestroyed$: new Subject<void>();
    
    ngOnInit() {
      this
        .store$
        .let(getCurrentUser)
        .takeUntil(this.componentDestroyed$)
        .do(_ => this.router.navigate(['/app']))
        .subscribe();
    }
    
    ngOnDestroyed() {
      this.componentDestroyed$.next();
      this.componentDestroyed$.complete();
    }
    

    【讨论】:

      【解决方案2】:

      您可以做的一件事是在您的订阅中使用 .skipUntil 运算符,如下所示;

      this.user$ = this.store$.select(state => state.user);
      this.user$.skipUntil( user => user.id );
      this.userSub = this.user$.subscribe(
          (user: IUser) => {
                 this.router.navigate(['/app']);
          }
      );
      

      那么您不需要订阅中的条件。

      【讨论】:

      • 我也确信您可以使用效果来调用路由器状态的导航操作,但是我自己还没有使用过这样的路由器状态。
      猜你喜欢
      • 1970-01-01
      • 2019-12-16
      • 1970-01-01
      • 2016-09-21
      • 2019-12-14
      • 2017-05-02
      • 2017-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多