YouTube video for this article
I implemented the Account Menu in Angular Movies with StateAdapt and the code decreased by 52%.
Nested state again
As in the last feature, RxAngular had a state shape like { loggedIn: boolean }
, whereas StateAdapt only needed a boolean.
Effects?
However, what really made a difference was removing unnecessary side-effects. RxAngular had these:
this.effects.register(this.ui.signOut$, this.authEffects.signOut);
this.effects.register(
this.ui.signIn$,
this.authEffects.approveRequestToken
);
So the template was calling ui.signOut$.next($event)
and ui.signIn$.next($event)
, when it could have just been calling authEffects.signOut
and authEffects.approveRequestToken
directly. I did end up creating pass-through class properties, because most Angular devs get a little uncomfortable with templates directly referencing services. But that was just 2 lines of code in my StateAdapt version:
signOut = this.authEffects.signOut;
signIn = this.authEffects.approveRequestToken;
It also allowed me to delete this from the RxAngular implementation:
type Actions = {
signOut: Event;
signIn: Event;
};
Imports, providers, constructor
RxAngular's implementation had more imports and providers, so the constructor was pretty fat. When I removed them, it collapsed from
constructor(
private authEffects: AuthEffects,
private authState: AuthState,
private state: RxState<{ loggedIn: boolean }>,
private effects: RxEffects,
private actionsF: RxActionFactory<Actions>
) {
to
constructor(private authEffects: AuthEffects, private authState: AuthState) {}
StateAdapt only had 2 imports: adapt
and booleanAdapter
. adapt
needs a provider that is required once per app (since a global Redux-like store is created behind the scenes), so adapt
needs to be injected. However, I like the inject
function instead of providing things in the constructor. Especially for libraries.
Similarities
I love RxAngular's connect
method. StateAdapt has something almost identical. Look at how this from RxAngular
this.state.connect(
'loggedIn',
this.authState.accountId$.pipe(map((s) => s !== null))
);
changes to this in StateAdapt
accountIdTruthy$ = this.authState.accountId$.pipe(
map((s) => s !== null),
toSource('accountIdTruthy$')
);
loggedIn = adapt(['loggedIn', false, booleanAdapter], this.accountIdTruthy$);
When passed in like that, this.accountIdTruthy$
will output to the set
method of booleanAdapter
(or whatever adapter is passed in). If there was a property like isLoggedIn
, you could control it like { setIsLoggedIn: this.accountIdTruthy$ }
.
RxAngular and StateAdapt are very similar to each other. They are the most reactive state management libraries that I know of for Angular. I wrote about this in a previous article: Choosing a State Management Library for Progressive Reactivity in Angular.
Conclusion
For a full comparison, see the commit here.
The features in Angular Movies will be getting more complex from here on. I expect RxAngular to be closer to StateAdapt in terms of code size. And while minimalism can be more readable, it is not the only metric to judge a library by. RxAngular is becoming very popular, the documentation is great, and in general has great support. That's why RxAngular is still currently my top pick for state management in Angular. StateAdapt is still a work in progress. I need to apply it to many more projects before I can have the confidence to release version 1.0. If you think it has potential, I'd appreciate a star, and I'd love for you to try it out and share your thoughts.
Thanks!
Edit: The Angular Movies app is a little buggy, so I'm going go on a detour and do a few conversions from NGXS and NgRx. But I'm looking forward to working inside RxAngular code again soon after that!
Top comments (2)
This is a manipulative conclusion, because a 80% of real world apps consists of combination 'connect' and 'select' calls, where stateadapt need much more boilerplate code. In addition rx-angulars select has built-in filtration for undefined values, which made real code much more shorter.
Find me a perfect example app and I'll do a new comparison. There are no perfect examples. But I haven't found a project yet where RxAngular was less code, so I don't feel that I cherry-picked anything.
StateAdapt also filters out undefined values. It's a very minor thing and I don't think I've taken advantage of it more than once or twice.