NGXS: Property 'stream$' is used before its initialization

Viewed 609

At first glance, it seems a default behavior of angular component life cycle logic that because of component properties did not initialized yet so stream$ cannot have assignment before component initialization complete:

@Component({
  selector: 'app-component',
  template: `<p>app works!</p>`,
})
export class AppComponent implements OnInit {
  @Select(AppState.getItems)
  stream$: Observable<string[]>;

  firstItemStream$: Observable<{ selectedItem: string }> = this.stream$ // error occurs here
  .pipe(
    find(({ itemId }) => itemId === 0),
  );

  ...

Quoted from NgXs:

APP_INITIALIZER is resolved after NGXS states are initialized. They are initialized by the NgxsModule that is imported into the AppModule. The ngxsOnInit method on states is also invoked before the APP_INITIALIZER token is resolved.

Above code works as expected but typescript error still occurs. Is there any workaround from this?

Also I decided to not open an issue to typescript opensource project because of it might also be about NgXs lifecycle itself.

2 Answers

It sounds like this scenario for using select decorator.

So you'd need update the declaration to:

@Select(AppState.getItems) stream$!: Observable<string[]>;

If you want to use stream$ inside the .ts code as another source, you need to define the property like so:

@Component({
  selector: 'app-component',
  template: `<p>app works!</p>`,
})
export class AppComponent implements OnInit {
  stream$: Observable<string[]>;
  firstItemStream$: Observable<{selectedItem: string}>;

  constructor(private readonly _store: Store) {
    this.stream$ = this.store.select(AppState.getItems);
    this.firstItemStream$ = this.stream$
      .pipe(
        find(({itemId}) => itemId === 0),
      );
  }
}

Note: I assume AppState.getItems is a pure function that receives a state and returns a given substate.

Here's the documentation.

Related