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
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
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); // > π
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>
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: π₯ } // > π₯
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) // > π
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>
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:πΈ }
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!
Top comments (9)
Great job!. This package is pure joy π€©. I find it a good choice for prototyping due to smooth DX. Glad you thought about proxifying the
.pipe
method:It's something I didn't think about for the first time
Ah, I'm very glad you enjoyed this update, Franciszek!
Yeah, recursive proxying together with fn calls is crazy:
I bet it's not practical. Just π€ͺ
Also, a weird thing I've noticed: ideas just happen to naturally pop up while exploring. I'll share some rxjs-autorun tricks this week β so far, two features we just discovered, not intentionally invented! π€―
It's fun in a good way. A lot of libraries use
Proxy
. So it's not some crazy niche. For example I like the pipeline operator:Not a big change but it's not standardized.
Should I hold my horses or go for it and show code like that to others?
Pipeline looks promising π
I was so fascinated that added
|>
to my RxJS playground: thinkrx.io/rxjs/js-pipeline/ , but with a lot of warning signs β οΈI'm not sure that we can openly use it for teaching or openly speaking about RxJS, probably just among those who we know wouldn't be confused by it. In the near future, at least.
--
Btw, about combining strings, this came out of
rxjs-autorun
(not my idea):Basically,
tracktag
turns a template string into acomputed
expression from autorun.Try it at stackblitz.com/edit/rxjs-autorun-t...
--
Which kinda automatically lead to HTML tags:
Try it at stackblitz.com/edit/rxjs-autorun-h...
--
Sorry for spamming you again with a million links. It's because you're among the few with whom I can share it π€·ββοΈ
Sorry for not responding for soooooo long π€‘. Shame on me
I don't see much potential in the
tracktag
thing. I think we should take a broader perspective. I lovecomputed
and<$>
.Why? because it makes code terser and paradoxically more explicit. And it's not just my alienated opinion. Those ideas are already implemented in Svelte, which brings increasingly more attention last time.
Some Svelte with RxJs bits:
The
$
prefix auto-subscribes and unsubscribes toObservable
. You can also:And the strong stuff:
working demo here
I would like to see those ideas beyond Svelte on a more general/agnostic field. Therefore I am looking forward to your work on this topic
How possible to pass
s.title
directly into input value π€I try this in codesandbox, it did throwing an error with
invalid value prop value on <input> tag.
Hey, t7yang! A totally valid question π
I wanted to show the idea w/o binding to any framework, so the code is somwehwat pseudocodish: some frameworks need adaptations for RxJS (regardless of whether we have a proxy or not)
In RecksJS it can be used as is (because Recks loves Observables π)
In Angular,
| async
pipe would help to consume values, but the handler would look differentFor React you can try <$> rxjs elements. It exports a
$input
:Here, try this code online π
Or you can use one of many Observable hooks: re-rxjs/react-rxjs, crimx/observable-hooks and LeetCode-OpenSource/rxjs-hooks
βοΈ But be cautious not to recreate Observables on each render: use some
useConst
analog.I haven't studied how to adapt RxJS to other frameworks, but you got a general idea.
Please, ping me if you have any questions left
π
Got it. I am Angular developer, async pipe should work well with this.
ReckJS and <$> pretty interesting. I saw ReckJS before, cool π₯³
Thanks, I'm glad you enjoyed it π
Ah, yeah, Angular is very powerful! And don't forget about the
onPush
change detection strategy! π