RxJS Proxy: 3 new features

Kostia Palchyk - Oct 23 '20 - - Dev Community

amazing header photo by Zach Kadolph

Hi! ๐Ÿ‘‹ In the previous post, I've introduced you to rxjs-proxify that turns your Observable into an Object of Observables:

const o = of({ msg: 'Hello' }, { msg: 'World' });
const p = proxify(o);
p.msg.subscribe(console.log); // > Hello > World
Enter fullscreen mode Exit fullscreen mode

Today I'll show you what new abilities you get with the recent 0.0.10 release: now proxify can be applied not only on Observables but also on Subjects and BehaviorSubjects. Also, we get a statify method that will help you manage the local state!

tl;dr try & install: github.com/kosich/rxjs-proxify

๐Ÿ“– Intro

Observables, Subjects, and BehaviorSubjects

Left to right: Observable, Subject, and BehaviorSubject. Cute photo by The Lucky Neko.

Observable Proxy (already familiar to you)
subscribe at any depth

const observable = proxify( of({ p: '๐Ÿ‘' }) );
observable.subscribe(console.log); // > { p: ๐Ÿ‘ }
observable.p.subscribe(console.log); // > ๐Ÿ‘
Enter fullscreen mode Exit fullscreen mode

It will be handy if you need to access many sub-properties on your streams:

// framework agnostic model
const { title, body } = proxify( fetchArticle() );
// framework agnostic view
<article>
  <Title value={ title } />
  <Body value={ body } />
</article>
Enter fullscreen mode Exit fullscreen mode

Note that here we're creating two separate Observables, so you'll probably want to .pipe( share() ) inside fetchArticle.


Subject Proxy
subscribe at any depth, push at the root

const subject = proxify(new Subject<{ p: string }>());
subject.subscribe(console.log);
subject.p.subscribe(console.log);
subject.next({ p: '๐Ÿฅ' }); // > { p: ๐Ÿฅ } // > ๐Ÿฅ
Enter fullscreen mode Exit fullscreen mode

While you have all the benefits of Observable Proxy, you can also update the whole Subject value.


BehaviorSubject Proxy

subscribe at any depth, push at any depth, synchronously read the current state

const behavior = proxify(new BehaviorSubject({ p: '๐Ÿ–' }));
behavior.p.subscribe(console.log); // > ๐Ÿ–
behavior.p.next('๐Ÿ‡'); // > ๐Ÿ‡
console.log(behavior.p.value) // > ๐Ÿ‡
Enter fullscreen mode Exit fullscreen mode

In addition to Observable Proxy, you can synchronously read and update the state at any level!

// model
const s = proxify(
  new BehaviorSubject({ title: '', checked: false })
);
// view
<div>
  <input
    value={ s.title }
    onChange={ e => s.title.next(e.target.value) } />
  <input
    type="checkbox"
    checked={ s.checked }
    onChange={ e => s.checked.next(e.target.checked) } />
</div>
Enter fullscreen mode Exit fullscreen mode

State proxy

And we also export a statify function that creates a BehaviorSubject Proxy with a distinctUntilChanged on all its properties:

// create a state
const state = statify({ a: '๐Ÿฐ', z: '๐Ÿก' });

// listen to & log root state changes
state.subscribe(console.log); //> { a:๐Ÿฐ z:๐Ÿก }

// update particular substate
state.a.next('๐Ÿ‡'); //> { a:๐Ÿ‡ z:๐Ÿก }
state.a.next('๐Ÿ‡'); //> same value, no update

// read current values
console.log(state.z.value + state.a.value); //> ๐Ÿก๐Ÿ‡

// update root state, still logging
state.next({ a: '๐Ÿ‡', z: 'โ˜๏ธ' }) //> { a:๐Ÿ‡ z:โ˜๏ธ }

// and thenโ€ฆ
state.z.next('๐ŸŒ™');   //> { a:๐Ÿ‡  z:๐ŸŒ™ }
state.a.next('๐Ÿ‡๐Ÿ‘€'); //> { a:๐Ÿ‡๐Ÿ‘€ z:๐ŸŒ™ }
state.z.next('๐Ÿ›ธ')    //> { a:๐Ÿ‡๐Ÿ‘€ z:๐Ÿ›ธ }
state.a.next('๐Ÿ’จ');   //> { a:๐Ÿ’จ  z:๐Ÿ›ธ }
Enter fullscreen mode Exit fullscreen mode

That's it! Just a few words before you go:

๐ŸŽ‰ Outro

You can try proxify online.

And you'll find more examples and the installation guide at github.com/kosich/rxjs-proxify. Hope you'll find these little tools useful!

If you enjoyed reading โ€” please, indicate that with โค๏ธ ๐Ÿฆ„ ๐Ÿ“˜ buttons

Follow me here and on twitter for more RxJS, React, and JS posts!

Thank you for reading this article! Stay reactive and have a nice day ๐Ÿ™‚

And thanks to @fkrasnowski for discussing with me and polishing this idea in the previous post comments!

. . . . . . . . . . . . . . . . .