用户注销时从ngrx / redux商店清除状态的问题

时间:2017-04-17 18:21:31

标签: ngrx reselect ngrx-effects

我的应用使用 ngrx / rxjs 。我依靠ngrx效果来从商店注销和清除状态。

不幸的是,因为我的一个组件通过选择器订阅了商店(见下文:getLatestMessagesByCounterParty),并且因为在销毁此组件之前状态已被清除,我收到以下错误:

  

错误TypeError:无法读取null的属性“id”       at getCurrentUserAccountId

...表明currentUserAccountnull,这是非常符合逻辑的,因为我刚从商店清除了状态。

以下是signout$效果:

  @Effect()
  signout$: Observable<Action> = this.actions$
    .ofType(authenticated.ActionTypes.SIGNOUT)
    .switchMap(() =>
      this.sessionSignoutService.signout()
        .do(() => {
          localStorage.removeItem('authenticated');
          localStorage.removeItem('sessionToken');
        })
        .concatMap(() => [
          new ClearMessagesAction(null),
          new ClearUserAccountAction(null),//Error thrown here...
          go(['/signin'])//Never reached...
        ]));

以下是订阅登录状态的组件:

  ngOnInit() {
    this.store.select(fromRoot.getLatestMessagesByCounterParty)
      .subscribe(latestMessages => this.latestMessages = this.messageService.sortMessagesByDate(latestMessages, this.numberOfConversations));
  }

相关选择者:

...
const getCurrentUserAccountId = (state: State) => state.userAccount.currentUserAccount.id;
const getMessagesState = (state: State) => state.message.messages;

...
export const getLatestMessagesByCounterParty = createSelector(getCurrentUserAccountId, getMessagesState, fromMessage.latestMessagesByCounterParty);

我正在寻找关于在何处,何时以及如何从商店中清除状态的最佳实践。理想情况下,我希望在订阅组件被销毁的最后一个可能的时间执行此操作。

有人可以提出建议吗?

修改:让我进一步完善我的评论。我上面的代码应该如下所示。

   .concatMap(() => [
      new ClearMessagesAction(null),
      new ClearUserAccountAction(null),//Error thrown right after this action because selector cannot find id variable on state
      go(['/signin'])//Never reached...
    ]));

1 个答案:

答案 0 :(得分:0)

正如@cgatian所说,你可能会使用过滤器。但是这里的代码背后会发生什么:

.concatMap(() => [
  new ClearMessagesAction(null),
  new ClearUserAccountAction(null),//Error thrown here...
  go(['/signin'])//Never reached...
]));

您首先发出行动ClearMessagesAction(null) 那个动作将由你的减速器处理 ___将生产新的国家 ___您的选择器将在
之后立即触发 ___会发生错误,因为你最终得到了一个不一致的商店(正如你所期望的那样,同一时间和选择者开始之前发送了另一个动作ClearUserAccountAction(null)

为避免状态不一致,您应该做的是:
  - 创建在两个reducer中处理的一个操作。这样,您的减速器都将被修改,只有这样,选择器才会启动   - 使用允许您将多个动作分配为一个的库(如redux-batched-actions)。这样你可以写出类似的东西:

batchActions([
  new ClearMessagesAction(null), --> selectors not triggered yet
  new ClearUserAccountAction(null) --> selectors not triggered yet
]); --> selectors triggered now