DEV Community

Cover image for Reactive Services with RxJS
Aliaksei Kuncevič
Aliaksei Kuncevič

Posted on ā€¢ Edited on

6 2

Reactive Services with RxJS

This is the first article, aka State Management Level 1 of the series Progressive State Management.

There are a lot of state management solutions that are available for Angular. However, do we always need to bring a fully-featured state management solution into our apps? Let's think about it.

Some main challenges building single-page applications we have to tackle are component communication and data flow. So that problems can be solved just by bringing the state management solution. However, state management solutions may introduce an additional level of complexity. As a result of that applications can become too hard and too expensive to maintain in the long run. So we should consider using state management solutions very carefully, based on the particular use-case scenario and remember about all the costs that come with that.

Being an Angular developer implies to be familiar with the basic concepts of RxJS. Which leads to the question of why don't we just use the powers or RxJS BehaviorSubject to solve the component communication? This way we can manage the data flow in our applications without introducing additional complexity. So, by using RxJS BehaviorSubject we can keep the solution simple, this approach works well on a small to medium scale. Let's see how we can achieve that.

Here is how reactive service might look like:

export class CounterService {
private data$ = new BehaviorSubject<Counter>(initialState);
state$ = this.data$.asObservable();
constructor() {}
public setValue1(value1): void {
const currentData = this.data$.getValue();
this.data$.next({ ...currentData, value1: currentData.value1 + value1 });
}
public setValue2(value2: number): void {
const currentData = this.data$.getValue();
this.data$.next({ ...currentData, value2: currentData.value2 + value2 });
}
public setValue3(value3: number): void {
const currentData = this.data$.getValue();
this.data$.next({ ...currentData, value3: currentData.value3 + value3 });
}
public sum(): Observable<number> {
return this.data$.pipe(map((x) => x.value1 + x.value2 + x.value3));
}
}

Can we improve that code? - yes, we can.

What we can do now is to reduce a bit of boilerplate in our reactive service by using an rx-service library

rx-service is a very simple library that wraps BehaviorSubject and provides utility functions on top of that. Methods like setState(), getState(), resetState() are available to manipulate the state of the BehaviorSubject. The local state exposed via the observable state$ variable.

That is how our code now look like using rx-service:

export class CounterService extends RxService<Counter> {
constructor() {
super(initialState);
}
public setValue1(value1): void {
this.setState((state) => ({ ...state, value1: state.value1 + value1 }));
}
public setValue2(value2: number): void {
this.setState((state) => ({ ...state, value2: state.value2 + value2 }));
}
public setValue3(value3: number): void {
this.setState((state) => ({ ...state, value3: state.value3 + value3 }));
}
public sum(): Observable<number> {
return this.state$.pipe(map((x) => x.value1 + x.value2 + x.value3));
}
}

The benefit of using the rx-service library is that it abstracts BehaviorSubject so the code of your services becomes cleaner. Also, it allows you to unify the way you implement reactive services across your applications. So the code you write becomes more maintainable and easier to read.

That is how to consume the reactive service within component class:

export class ParentComponent implements OnInit {
value$: Observable<number>;
constructor(private counterStore: CounterService) {}
ngOnInit(): void {
this.value$ = this.counterStore.state$.pipe(map((x) => x.value1));
}
updateValue(value: number): void {
this.counterStore.setValue1(value);
}
}

You can introduce as many reactive services in your application as you want based on your exact use-case. In the long run, when the size and complexity of your application grow you may decide that you have enough reactive services in your application. Therefore, at this stage you may just replace reactive services with a proper state management solution of your choice.


My name is Aliaksei Kuncevič. I am teaching Angular and Web Technology. Helping dev teams to adopt Angular in the most efficient way. GDE, member of the NGXS Core Team.

I hope you find this content helpful and if so, please help to spread this article so more people can benefit from it.

If you want to learn more Angular tips and tricks join my newsletter at kuncevic.dev

If you want to know more about Angular subscribe for Angular Rocks podcast šŸŽ™

You can find the source code for this article here

Top comments (0)

šŸ‘‹ Kindness is contagious

Please leave a ā¤ļø or a friendly comment on this post if you found it helpful!

Okay