【问题标题】:Angular router navigation inside NgRx effectNgRx 效果中的角度路由器导航
【发布时间】:2021-06-25 12:37:24
【问题描述】:

Angular 路由器在 NgRx 效果中的使用是否有任何限制?

我刚开始学习 NgRx,我有以下代码:

@Effect() public authenticate$ = this.actions$
    .ofType(authenticationActions.AUTHENTICATE)
        .switchMap((action: AuthenticateAction) => this.authenticationService.authenticate(action.payload)
            .map((data: TokenData) => {
                const user: User = {
                    token: data.token,
                    username: 'dummy',
                };
                console.log(data);
                this.router.navigateByUrl('/');
                return new authenticationActions.AuthenticateSuccessAction(user);
            })
            .catch(error => { console.log(error); return Observable.throw(error); })
        );

控制台记录了数据变量,AuthenticateSuccessAction 动作被触发,所以路由器线路正在执行,但导航没有发生。

【问题讨论】:

  • 这应该可以正常工作,也许在导航到 root 之前尝试不同的 URL 以确保它不是错误? this.router.navigateByUrl('/login');确保您没有使用 AuthGuard 之类的东西将您重定向回登录屏幕。
  • 我已经尝试了不同的 url,还禁用了所有防护,并在登录页面中创建了一个测试按钮以使用相同的语句并导航。问题是效果里面的那个语句。这很奇怪
  • 我的实现与您类似,并且能够毫无问题地路由我的应用程序。这很愚蠢,但请确保您已在构造函数中注入了路由器。
  • tap 操作符中进行导航(在旧版本的 rxjs 中,它被称为 do)。

标签: angular ngrx angular-router ngrx-effects


【解决方案1】:
@Effect() public authenticate$ = this.actions$.pipe(
    ofType(authenticationActions.AUTHENTICATE),
     map(action => action.payload),
    exhaustMap((auth: any) => 
      this.authenticationService.authenticate(auth)
        .map((data: TokenData) => {
            return user: User = {
                token: data.token,
                username: 'dummy',
            };
        }).catch(error => { console.log(error); return Observable.throw(error); 
       }).pipe(
          map(user =>new authenticationActions.AuthenticateSuccessAction(user))
        )
    );)

  @Effect({ dispatch: false })
   loginSuccess$ = this.actions$.pipe(
     ofType(authenticationActions.AuthenticateSuccessAction),
     tap(() => this.router.navigate(['/']))
   );

使用exhaustMap,当你发送'AuthenticateSuccessAction'动作时,做另一个重定向效果。

我个人喜欢把所有的服务和效果分开,然后你可以在登录成功后使用catchError()操作符在登录失败的情况下调度另一个动作。

希望这行得通。 PS:我没有验证这个答案,但逻辑是这样的。

【讨论】:

  • 那个 dispatch: false 是关键 ;-)
  • @Stuart Allen 谢谢朋友!我想知道为什么效果一直在循环
  • 有趣的是,您调度了一个动作,该动作同时发送到 reducer 和下一个效果处理程序。我会看看这是否有效,但我希望它有效。
【解决方案2】:

应该有一种方法允许不为重定向创建单独的效果,例如

this.actions$.pipe(
  ofType(authenticationActions.AUTHENTICATE),
  switchMap(action =>
    this.authenticationService.authenticate(action.payload).pipe(
      map(data => new authenticationActions.successAction(data)),
      tap(() => this.router.navigate(['/'])),
      catchError(error => new authenticationActions.failAction(error))
    )
);

问题是,如果服务调用失败,tap 将不会被调用,如果失败,maptap 将被跳过以支持catchError

【讨论】:

    【解决方案3】:

    根据 m.akbari 的响应,如果他们使用不同的操作,“dispatch : false”到最后一个

    关键是“dispatch : false”,如果没有指明会生成无限循环

     loginNavigate$ = createEffect(
        () => this.actions$.pipe(
            ofType(usuariosActions.loginUsuarioSuccess),
            tap(() => {
                console.log('iniciando la navegacion');
    
                this.router.navigate(['/']);
            })
        ), { dispatch: false }
    );
    

    【讨论】:

      猜你喜欢
      • 2019-02-24
      • 2021-10-01
      • 2020-02-25
      • 1970-01-01
      • 1970-01-01
      • 2019-07-02
      • 2019-05-03
      • 1970-01-01
      • 2019-09-27
      相关资源
      最近更新 更多