【问题标题】:Unable to fetch the latest state from different stores at once using Ngrx无法使用 Ngrx 一次从不同的商店获取最新状态
【发布时间】:2021-07-25 21:56:14
【问题描述】:

我在我的 Angular 应用程序中使用 Ngrx 从存储中获取数据。
我创建了多个存储:上下文、决策和状态,以在对象之间创建功能分离。

我有一个案例,UI 需要同时轮询 2 个不同商店的最新状态,以便启用/禁用按钮。

这是一个示例,其中titi 的状态在单击按钮后从其他组件更新。
我的问题是,我的实际代码无法获得this.titi 的最新状态!
这是我的代码:

export class MyComponent implements OnInit, OnDestroy {

   private titi: Titi;
   private toto: Toto;
   private unsubscribe$: Subject<void> = new Subject<void>();

   constructor(private store: Store<State>) {}

   ngOnInit() {

      this.store.pipe(
         select(selectTiti),
         takeUntil(this.unsubscribe$)
      ).subscribe(state => {
         this.titi= state.titi;
      });

      this.store.pipe(
         select(selectTata),
         takeUntil(this.unsubscribe$)
      ).subscribe(state => {
         this.tata= state.tata;
      });

   }

   public isBtnDisabled() {
      return this.titi === 'latest value of titi' && this.tata === 'latest value of tata';
   }

   ....

   ngOnDestroy(): void {
     this.unsubscribe$.next();
     this.unsubscribe$.complete();
   }
}

和用户界面:

<button [disabled] = 'isBtnDisabled()'></button>

【问题讨论】:

    标签: angular ngrx ngrx-store redux-observable


    【解决方案1】:

    您可以使用更被动的方式来做到这一点。 通过使用 combineLatest,如果值更改为存储,您将获得每个选择器的最新值:

    isDisabled$ = combineLatest(
      this.store.select(selectTiti),
      this.store.select(selectTata)
    ).pipe(
      map(([titi, tata]) => // do whatever you want to check the disabled status)
    );
    

    您可以在模板中使用异步管道进行订阅,这样您就不必依赖手动取消订阅组件:

    <button [disabled] = 'isDisabled$ | async'></button>
    

    所以最终的组件应该是这样的:

    export class MyComponent {
    
      public isDisabled$: Observable<boolean> = combineLatest(
      this.store.select(selectTiti),
      this.store.select(selectTata)
      ).pipe(
        map(([titi, tata]) => // do whatever you want to check the disabled status)
      );
    
       constructor(private store: Store<State>) {}
    }
    

    【讨论】:

    • 实际上我不能使用这种语法,因为在我的情况下,我需要在获取我为了示例而删除的商店后实现一些业务逻辑
    • 您可以将tap 运算符用于您的业务逻辑
    • 我尝试使用这种语法,但似乎 combineLatest() 已被弃用!我的 RxJs 版本是"rxjs": "^6.6.3"
    【解决方案2】:

    【讨论】:

    • 我认为每次根据功能需要添加一个新的选择器会以某种方式使我的应用程序过载:(
    • 创建选择器和根据您的答案编写代码有什么区别?好处是它只是一个纯函数,更容易测试,它可以记忆,易于分享,你不需要谷歌如何使用某些 RxJS 操作符。选择器是 3 到 5 行代码,你的答案是 8 行。
    【解决方案3】:

    最后,结合我发现清晰且接近我的实现的商店的解决方案是:

    ngOnInit() {
        this.store.pipe(
          select(selectTiti),
          withLatestFrom(this.store.pipe(select(selectTata))),
          takeUntil(this.unsubscribe$)
        ).subscribe(([titiState, tataState]) => {
          this.titi = titiState.titi;
          this.tata = tataState.tata;
        });
    }
    

    【讨论】:

    • 我的答案是-2!任何记下它的人都可以解释一下这个解决方案的缺点吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-21
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 2018-03-25
    • 1970-01-01
    • 2023-01-28
    相关资源
    最近更新 更多