There are several cases where you’d like to access a property of an object that isn’t already set like in this simple code :
jsonlet a = {} let c = a.b console.log(c) // logs undefined a.b = 1 console.log(c) // 😩 logs undefined
Obviously by just moving around one line of code in our first example, we can get this code to work.
jsonlet a = {} a.b = 1 let c = a.b console.log(c) // 🎉 logs 1 console.log(c) // 🎉 logs 1
We see here one of the limits of imperative code : the same bits of computation will behave differently depending on the order/context they are run.
Even the most “reactive” UI frameworks ask you to register/define your data/store prior to calling it in your components.
Wouldn’t it be great for our component to just know the reference of the data it needs but don’t worry if it has yet been defined or not ?
This would enable to decouple completely the UI and the logic !
We are going to explore a way to write this simple code in a pure declarative way.
Let’s first try to solve the first example with simple Rxjs logic
jsonconst a = new BehaviorSubject({}) const c = new BehaviorSubject(null) a.pipe(map(v => v.b)).subscribe(c) console.log(c.value) // logs undefined a.next({b:1}) console.log(c.value) // Tadaa ! 😁 logs 1
At Potions we created a Store class that enables
jsonconst $ = new Store() $.a = {} $.c = $.a.b console.log($.c.value) // logs undefined $.a = {b:1} console.log($.c.value) // Tadaa ! 😁 logs 1
Store is a proxy of a BehaviorSubject where every property… is a store itself.