маршрутизация ngrx при отправке действия

Я использую ngrx, чтобы сохранить свое пользовательское состояние. Под пользовательским состоянием я подразумеваю объект класса IUser с некоторыми пользовательскими свойствами.

Я установил несколько действий ('USER_LOGIN', 'USER_LOGIN_SUCCESS' and 'USER_LOGJN_FAILED').

В настоящее время, когда отправляется USER_LOGIN_SUCCESS, редуктор назначает новую информацию о пользователе моему полю хранилища 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. Могу ли я сосредоточить все это поведение на одном инъекционном препарате?

Любые идеи?


person Jordi    schedule 13.03.2017    source источник


Ответы (2)


Да, вы можете сделать это более элегантно.
Давайте рассмотрим это шаг за шагом :)

1) Используйте filter из rxjs вместо оператора if

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

2) Избегайте обработки подписок по очереди
(есть отличная статья от Бена Леша на 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

Используйте do или map для обработки своей логики перед подпиской.
- do если вам просто нужно что-то сделать
- map если вы хотите вернуть результат

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

(CF следующая часть "почему")

4) Используйте "селекторы", если хотите повторно использовать или экспортировать логику

Если бы мне пришлось догадываться о вашем коде, я полагаю, что ваш user $ является текущим пользователем. Тот, что подключен правильно? И вам, возможно, придется скопировать весь этот код в другую часть вашего приложения, чтобы снова найти этого пользователя.

Это хороший вариант использования "селектора" .
(Я экспортировал здесь 2 функции, чтобы этот код был удобен для AOT).

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();

В итоге

a user.selector.ts :

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

a 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();
}
person maxime1992    schedule 13.03.2017

Одна вещь, которую вы можете сделать, чтобы привести в порядок, - это использовать оператор .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']);
    }
);

тогда вам не нужно условие внутри подписки.

person tubbsy    schedule 13.03.2017
comment
Я также уверен, что вы могли бы использовать эффект для вызова действия навигации по состоянию вашего маршрутизатора, однако я сам еще не использовал такое состояние маршрутизатора. - person tubbsy; 13.03.2017