DEV Community

Cover image for 50% less code: RxAngular vs StateAdapt 2. Angular Movies 1. App Shell
Mike Pearson for This is Angular

Posted on • Updated on

50% less code: RxAngular vs StateAdapt 2. Angular Movies 1. App Shell

YouTube video for this article

I implemented the Angular Movies app shell with StateAdapt and the code decreased by 50%.

Todo MVC UI

What made the difference?

The app shell state was very simple. It was just a boolean for whether the sidenav was open or not.

This made a small difference in RxAngular vs StateAdapt, because RxAngular has to have an object to manage, but StateAdapt can manage anything, so I just had the state be a boolean. It's easy to change later if needed.

Another difference was that RxAngular was wired up in a way where a URL change would cause a method to be called as a side-effect, when it could have been reactive even in RxAngular. I fixed that in StateAdapt though, so I'm sure RxAngular could have been a couple of lines less if it wasn't done that way. But I will always make sure things are as reactive as possible when I use StateAdapt.

Here's the main code for StateAdapt:

  urlChange$ = this.router.events.pipe(
    filter((e) => e instanceof NavigationEnd),
    map((e) => (e as NavigationEnd).urlAfterRedirects),
    distinctUntilChanged(),
    toSource('urlChange$')
  );

  sideDrawerOpen = adapt(['app-shell.sideDrawerOpen', false, booleanAdapter], {
    setFalse: this.urlChange$,
  });
Enter fullscreen mode Exit fullscreen mode

In RxAngular, that false had to be this:

    this.state.set({ sideDrawerOpen: false });
Enter fullscreen mode Exit fullscreen mode

In the template in StateAdapt, I just called the source that's available by default in the sideDrawerOpen store, but RxAngular has to react to an observable:

    this.state.connect('sideDrawerOpen', this.ui.sideDrawerOpenToggle$);
Enter fullscreen mode Exit fullscreen mode

Both implementations have the exact same number of imperative statements: The template has to call .next() in one case, and set() in another.

The weirdest part in RxAngular was this:

    this.effects.register(
      this.router.events.pipe(
        filter((e) => e instanceof NavigationEnd),
        map((e) => (e as NavigationEnd).urlAfterRedirects),
        distinctUntilChanged()
      ),
      () => this.closeSidenav()
    );
// ...
  closeSidenav = () => {
    this.ui.sideDrawerOpenToggle(false);
  };
Enter fullscreen mode Exit fullscreen mode

That was the only place the closeSidenav method was invoked. But that "effect" could just have easily been connected like this:

this.state.connect('sideDrawerOpen', urlChange$, () => false);
// I might be wrong on the exact syntax, but I think that's right.
Enter fullscreen mode Exit fullscreen mode

And all of that was in an init method that was called imperatively from an ngOnInit method, which was itself called imperatively by Angular:

init() {
// ...
// RxAngular connections, `set`s, effects
// ...
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

For a full comparison, see this pull request (but please don't open it).

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!


Repo

StateAdapt

RxAngular

Twitter

Top comments (0)