Как использовать селектор ngrx, параметр которого зависит от другого селектора - PullRequest
0 голосов
/ 22 сентября 2019

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

Сначала я загружаю все задания и задачи из базы данных, но они нея вовремя возвращаюсь к селекторам, и я получаю сообщение об ошибке, потому что this.task не определено, что, как я полагаю, препятствует повторному запуску наблюдаемого.

Есть ли способ дождаться возврата данных, прежде чем селекторы попытаются извлечь данные из хранилища?

this.store.dispatch(fromTasks.loadAllTasks());
this.store.dispatch(fromJobs.loadAllJobs());

taskSubscription$ = this.store.pipe(
	select(fromTask.getSelectedTask),
	tap(task => this.task = task)).subscribe()

jobSubscription$ = this.store.pipe(
	select(fromJob.getJobById, {jobId: this.task.jobId}),
	tap(job => this.job = job)).subscribe();

Ответы [ 2 ]

1 голос
/ 22 сентября 2019

Вот подход, который вы можете рассмотреть:

1) Селектор getSelectedTask возврат null если нет выбранной задачи

export const getSelectedTask = createSelector(
  selectEntities,
  getSelectedTaskId,
  (entities: Dictionary<Task>, selectedId: number) => {
    return selectedId ? entities[selectedId] : null;
  }
)

2) Использование async pipe и *ngIf inside template

Component.ts

@Component({
  selector: 'my-component',
  ...
})
export class MyComponent {
  selectedTask$ = this.store.pipe(select(getSelectedTask));
...
}

Template.html

<ng-container *ngIf="selectedTask$ | async as selectedTask else noSelection">

  <my-task [task]="selectedTask"></my-task>
  // or 
  <span>{{ selectedTask.description }}</span>

</ng-container>

<ng-template #noSelection>
  Please select a task !
</ng-template>

При таком подходе вы будете использовать мощные наблюдаемые с угловым синтаксисом шаблона.Если пользователь отменит текущее задание, селектор getSelectedTask вернет null, и шаблон будет автоматически обновлен.

Тем не менее, вы можете продолжать использовать subscription, но в этом случае предпочтительнее установить значение внутри метода subscribe и обязательно отписаться.

@Component({
  selector: 'my-component',
  ...
})
export class MyComponent implements OnInit, OnDestroy {
  subscription: Subscription;
  selectedTask$ = this.store.pipe(select(getSelectedTask));
  selectedTask: Task;

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

  ngOnInit() {
    this.subscription = this.selectedTask$.subscribe(task 
      => this.selectedTask = task);
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}
1 голос
/ 22 сентября 2019

Вы можете попробовать использовать фильтр RxJS.

taskSubscription$ = this.store.pipe( select(fromTask.getSelectedTask), filter(task => !!task), tap(task => this.task = task)).subscribe()

...