Managing the state of Angular components can become complex as your component grows.
A simple approach to handle your component’s state is with component member variables and Angular’s default change detection. However, this approach is flawed for two reasons:
- Difficulty Scaling: Your component quickly becomes cluttered with member variables and messy templates.
- Performance Issues: You lack control over Angular’s change detection, ultimately hurting your application’s performance. This is because default change detection will run multiple times whenever a change is detected within the component: e.g. user events, timers, XHR, promises, etc. As an application grows, minimizing change detection code is crucial for a fast application that your users love.
To handle these issues, we can house the component’s state in a single
BehaviorSubject and use Angular’s built-in
async template pipe and
OnPush change detection to increase performance.
To learn more about
OnPush change detection, I recommend reading this article by Netanel Basal: https://netbasal.com/a-comprehensive-guide-to-angular-onpush-change-detection-strategy-5bac493074a4
Your component has one member variable called
state$ that houses the component’s state and then uses an
async pipe wrapper in the template to feed data into the template:
With this code, you can easily manage the basic states that 90% of your components use:
- Data is loading
- Data is found
- Data is not found
👍 The Upsides
- Cleaner templates: No more nesting
ng-containers that make the template cluttered and buggy:
The inner data observables will not be subscribed to until the outer ones are subscribed to causing much confusion and bugs!
2. Fine-grain control: We choose when to update the component’s state and change detection.
👎 The Downsides
Of course, no solution is perfect. Because we only have one
BehaviorSubject handling the state, which means we have to manually handle external subscriptions inside the component’s Typescript file.
Not to fear, I have provided a full solution to this problem with the code below. Feel free to use this abstract class throughout your application! 😁
RxJSBaseClass is separate so you can extend it to Angular services.
Here is the example code implemented with this full-solution:
Learning how Angular’s change detection works will give you insight into how you can better handle your component’s state.
Thanks for reading! 🤓