Codementor Events

How I Got Rid of State Observables in Angular

Published Mar 31, 2020
How I Got Rid of State Observables in Angular

When developing a complex SPA in Angular, using a state management library makes things so much easier.

The app store acts as a single source of truth and contains all the data that is fundamental to the correct functioning of the app. Thanks to the store, I can access or edit this data from any smart component (or container).

However, it can be frustrating to deal with all the subscriptions to the store; many times I have to deal with multiple @Select() in a single component, each of which returns an Observable of its correspondent property in the app store.

And for each of these Observables, I need to create a subscription that will be destroyed at the end of the component lifecycle…that’s a lot of code!

But what if we could get rid of all the Observables?

In the simplest cases, we can avoid explicit subscriptions using the async pipe, which will subscribe to the Observable and read the last value emitted for us.

Suppose that we have a @Select() decorator like this:

@Select(ListState.SelectAllItems) listItems: Observable<string[]>;

We can use it immediately with the <i>async</i> pipe in our HTML:

<ul>
 <li *ngFor="let item of listItems | async">
   {{item}}
 </li>
</ul>

On the other hand, many cases require us to subscribe to the Observables in our components so that we can use the values they emit in other methods.

(To learn about how to set up a store and see the above examples in a project, you can read my article <a href="https://medium.com/better-programming/how-to-create-a-simple-store-in-angular-577a8f21a3d6"> How to Create a Simple Store in Angular.</a>)

<hr>

Introducing @ngxs-labs/select-snapshot

<i>@ngxs-labs/select-snapshot</i> is an experimental feature for NGXS developed by NGXS Labs.

Even though it’s still not part of the official NGXS package, it is likely to become an official feature shortly. The package allows us to replace the <i>@Select()</i> decorator with <i>@SelectSnapshot()</i>.

But what’s the difference between them?

While the former returns an Observable we need to subscribe to, the latter subscribes to the store for us and returns the last value emitted! To see it in action, let’s install the package:

npm install @ngxs-labs/select-snapshot

And then, let’s include it in our appModule:

@NgModule({
declarations: [
AppComponent,
ListContainerComponent,
ListItemInputComponent,
ListComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule,
NgxsModule.forRoot([ListState]),
NgxsReduxDevtoolsPluginModule.forRoot(),
NgxsSelectSnapshotModule.forRoot()
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}

Now we can replace the <i>@Select()</i> decorator:

//@Select(ListState.SelectAllItems) listItems: Observable<string[]>;
@SelectSnapshot(ListState.SelectAllItems) listItems: string[];

And use the value emitted from the store without subscribing!

<ul>
 <li *ngFor="let item of listItems">
   {{item}}
 </li>
</ul>

Enjoy!

Discover and read more posts from Alessia Amitrano
get started