Using the constructor in order to select on the store and ngOnInit in order to dispatch from the store
Asked Answered
S

2

14

My question relates to dispatching & selecting from the ngrx store.

Let's look at the following code from the official example app:

export class CollectionPageComponent implements OnInit {
  books$: Observable<Book[]>;

  constructor(private store: Store<fromBooks.State>) {
    this.books$ = store.select(fromBooks.getBookCollection);
  }

  ngOnInit() {
    this.store.dispatch(new collection.Load());
  }
}

I would like to understand what motivated the choice of dispatching from ngOnInit and selecting from the constructor.

Can anyone please provide an explanation?

P.S. By the way, the above is sample code from the ngrx example app that can be found here: https://github.com/ngrx/platform/blob/master/example-app/app/books/containers/collection-page.ts

Salivate answered 29/10, 2017 at 17:12 Comment(1)
What seems to be confusing you? There are many ways to do something. This is not a wrong way. You could do the same with a resolver, or with http polling which starts from the moment your app initiates or many other ways...Windup
U
7

The constructor is executed when the class is instantiated and ensures proper initialization of the class´ fields. This is where Angular resolves providers you may pass as arguments in your constructor.

The ngOnInit lifecycle hook is called after the data-bound properties have been checked for the first time (inputs & outputs of the component). For a more detailed explanation see this question.

The motivation for selecting from ngrx store in the constructor and dispatching from ngOnInit as far as I understand it, is that selecting is part of initializing you component class. Since this.books$ is an Observable, it makes sense initialize it in the constructor so it is ready for use immediately after creation. Assuming the bookCollection.Load() emits a value to this.books$ you want this.books$ to be an observable of those books before an eventual value is emitted.

Since you want those values emitted to this.books$ it makes sense to dispatch the action in ngOnInit. This way you can ne certain that this.books$ is initialized.

This answer to a similar question might also be of help.

Undistinguished answered 16/11, 2017 at 9:35 Comment(1)
Don't forget the "?" to avoid Cannot read property of undefined error if the initial state is null. Something like this: store.select(fromBooks?.getBookCollection);Passable
B
-2

The main reason in my opinion is separation of concerns. The constructor is the place were you define all dependencies. So in this case getting the store and than selecting a slice of it.

Dispatching an actions though is part of logic that can be separated from the dependencies (if possible).

Think of a class with lots of dependencies and lots of actions. This helps to keep things separated. Everyone who will read the class can always look at the constructor to see what the dependencies are and is not obfuscated with any other logic.

Batholomew answered 2/11, 2017 at 9:15 Comment(2)
Hello Wheeler. Are you certain this is the case? Is it not rather related to the lifecycle of angular components and the difference between constructor and ngOnInit ?Salivate
It might depend but I also used dispatching actions in constructor before without any issue or side-effect.Batholomew

© 2022 - 2024 — McMap. All rights reserved.