2

我像这样从 NGRX/store 获得预订列表,数据正确输入,但在页面重新加载时消失。我必须更改路线才能将其取回。

ngOnInit() {

this.store.select(state => state.authState.profile).subscribe(profile => {

  this.profile = profile;
  if (this.profile) {
    this.userId = this.profile.$key;
  }
    });
    if (this.userId) {
    this.reservations$ = this.reservationService.loadUserReservations(this.userId);
  }
 }

   ngOnChanges() {
    if (this.userId) {
    this.reservations$ = 
    this.reservationService.loadUserReservations(this.userId);
      }

  }

不确定这是否足以说明问题的代码。

在我的身份验证服务中

this.auth$.authState.subscribe(user => {
  if (user) {

    const userData = user;
    const userRef = db.object("users/" + userData.uid);

    const dataToSet = {
      displayName: userData.providerData[0].displayName,
      email: userData.providerData[0].email,
      photoURL: userData.providerData[0].photoURL,
      providerId: userData.providerData[0].providerId,
      registeredAt: new Date()
    };

    userRef.take(1).subscribe((user) => {
      if (user.$exists()) {
        // console.log('user exists', user);
        this.store.dispatch(this.authActions.updateUserInfo(user));

      } else {
        // console.log('user does not exists');
        userRef.set(dataToSet)
          .then((result) => {
            // console.log(result)
          })
          .catch((error) => {
            // console.log(error);
          });
      }
    });
    // console.log('hello user', user);
    this.store.dispatch(this.authActions.loginSuccess(user));
  } else {
    this.store.dispatch(this.authActions.logOutUser());
  }
});

}

我正在使用 Firebase 并订阅 authState 更改。当用户登录时,我发送一个操作来更新商店,我只使用 authState.profile 来过滤用户的预订并且所有工作正常。我在 ngOnInit() 上设置了 observable reservations$。

4

1 回答 1

3

这里有几件事要说。

首先,store 只是一个普通的、内存中的 javascript 对象。这意味着在页面重新加载时它已经消失了。

其次,如果您需要任何类型的用户身份验证数据的持久性,那么您应该在用户登录时将该数据存储(您已经执行的操作)并另外将其存储到一些 localStorage 或 cookie 中。然后,您应该具有读取 localStorage/cookie 以获取身份验证数据并在页面重新加载(或任何页面加载,就此而言)重新填充存储的机制。[这是一个单独的问题,只是给你上下文]

现在,您可能永远不希望发生的一件事是,如果用户未登录(换句话说,如果存储中没有 authState 数据),他最终会访问您的预订组件。这正是正在发生的事情。

你有几个选择来解决这个问题。一种可能是最好的方法是让 AuthGuard 运行在 CanActivate 中,用于您的预订组件使用的路由。

所以,像这样的事情......

CheckAuthGuard:

canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
    return this.store.select(yourPartOfStateWhereAuthDataIs)
      .map(profileData => !!profileData)
      .take(1)
      .do(authenticated => {
        if (!authenticated) {
          this.router.navigate([ 'login' ], {
            queryParams: { referer: this.createUrl(route) }
          });
        }
      });
    }

然后在您的路由中,对于预订组件路由:

{
  path: '',
  component: ReservationsComponent,
  canActivate: [CheckAuthGuard]
}

这将确保:

  1. 如果用户最终使用预订组件 > 有 AuthData
  2. 如果商店中没有 AuthData,当尝试去预订时 > 用户将被重定向到登录页面

现在,关于获得预订的另一件事。似乎您不是从商店获得预订,而是直接从服务获得预订。我建议实际上是为 Reservations 组件多加一个警卫,并且这样做:

  1. 加载预订(通过调度 ngrx 操作,这将反过来调用您已经拥有的服务)
  2. 当您的商店充满注册数据时,您的守卫将允许进入预订组件
  3. 在您的预订组件中,您store.select(PartOfStoreWhereReservationsAre)将从那里执行并使用它们

信息可能有点太多,但我希望你能找到自己的方式;)

于 2017-07-25T18:16:50.420 回答