If a state implements the NgxsOnChanges interface, its ngxsOnChanges method respond when (re)sets state. The states' ngxsOnChanges methods are invoked in a topological sorted order going from parent to child. The first parameter is the NgxsSimpleChange object of current and previous state.
If a state implements the NgxsOnInit interface, its ngxsOnInit method will be invoked after all the states from the state's module definition have been initialized and pushed into the state stream. The states' ngxsOnInit methods are invoked in a topological sorted order going from parent to child. The first parameter is the StateContext where you can get the current state and dispatch actions as usual.
If a state implements the NgxsAfterBootstrap interface, its ngxsAfterBootstrap method will be invoked after the root view and all its children have been rendered, because Angular invokes functions, retrieved from the injector by APP_BOOTSTRAP_LISTENER token, only after creating and attaching ComponentRef of the root component to the tree of views.
exportinterfaceZooStateModel { animals:string[];}@State<ZooStateModel>({ name:'zoo', defaults: { animals: [] }})@Injectable()exportclassZooStateimplementsNgxsAfterBootstrap {ngxsAfterBootstrap(ctx:StateContext<ZooStateModel>) {console.log('The application has been fully rendered');ctx.dispatch(newGetAnimals()); }}
Lifecycle sequence
After creating the state by calling its constructor, NGXS calls the lifecycle hook methods in the following sequence at specific moments:
Feature Modules Order of Imports
If you have feature modules they need to be imported after the root module:
The APP_INITIALIZER is just a token that references Promise factories. If you've ever used the APP_INITIALIZER token, then you are already familiar with its syntax:
This token is injected into ApplicationInitStatus class. What does Angular do under the hood? It gets an instance of this class and invokes the runInitializers method:
All that it does inside this method is looping via the APP_INITIALIZER array (as it's a multi token) and invoking those factories, that you've provided in useFactory properties:
for (let i =0; i <this.appInits.length; i++) {constinitResult=this.appInits[i]();if (isPromise(initResult)) {asyncInitPromises.push(initResult); }}
Then asyncInitPromises are provided into Promise.all. That's all the magic. That's why the bootstrapModule returns a Promise:
Everything that we examined earlier is very important, because from this comes the fact that 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. Given the following code:
The above example is used only for demonstration purposes! This code will throw an error because the getVersion method is invoked before the version property is set. Why? Because the ngxsOnInit methods on states are invoked before the APP_INITIALIZER is invoked!
Solution
There are different solutions. Let's look at the simplest. The first solution would be to use the ngxsAfterBootstrap method: