Reactive primitives in JavaScript (and other cool stuff with OxJS)
Tags: javascript, reactivity, primitives, objects
Published: 2019-07-03 17:52:08

---
title: Reactive primitives in JavaScript (and other cool stuff with OxJS)
published: true
description: How to take reactivity to a greater level of mess
tags: javascript, reactivity, primitives, objects
---

Ok ok, I know what you are thinking: this is impossible!

![](https://www.drcommodore.it/wp-content/uploads/2019/03/dsmGaKWMeHXe9QuJtq_ys30PNfTGnMsRuHuo_MUzGCg.jpg)

&nbsp;

# And the delirium began
Some time ago I was wondering if it were possible to create _direct reactive relationships_ between entities in JavaScript.
In other words I would have liked to be able to write code conceptually represented by the following pseudo one:

```js
// create a source
const $source = { foo: 42 };

// create a reactive primitive that will be updated
// when the 'foo' field of the source changes
rx primitive = $source.foo;
primitive; // 42

// create a reactive object that will be updated
// when changes happen into the source
rx object = $source;
object; // { foo: 42 };

// change the 'foo' field source
$source.foo = 'hi';

// the reactive primitive was updated
primitive; // 'hi'
// the reactive object as well
object; // { foo: 'hi' }

// change the whole source
$source = { foo: { bar: 'baz' } };

// the reactive object was updated
object; // { foo: { bar: 'baz' } }
// the reactive primitive too, but unfortunately is no more a primitive
primitive; // { bar: 'baz' }
```

What's the point of such type of reactivity, that I like to define __encapsulated reactivity__ or __low-level reactivity__?
It helps to observe changes inside a structure that could easily become the source of truth in event-driven applications.
 
Let's talk about VueJS computed properties, from which I've took inspiration to build the raw reactivity system of OxJS. I'm not going to explain VueJS reactivity system here, but I can link [this interesting video series](https://www.vuemastery.com/courses/advanced-components/the-introduction) that contains lot of useful information.
For each Vue component, we can consider the union of the internal __data__ object and the __props__ that the component's parent has passed to it as the source of truth:
```js
export default {
    data() {
        // the internal data object
        return {
            age: 22
        }
    },

    props: {
        // a numerical multiplier prop
        multiplier: {
            type: Number,
            default: 1,
        }
    },

    // here the magic
    computed: {
        result() {
            return this.multiplier * this.age + 1;
        }
    }
}
```
Computed properties are a special type of properties that result from combining other properties of the component with some custom logic. In our example the `result` computed property will become the result of a mathematical operations that uses the `multiplier` prop and the `age` data property.
Every time one of those changes, the `result` property will be recomputed, hence the name, updating properly.

For VueJS developers computed properties are very useful and irreplaceable; the lifeblood of each VueJS component, because they make reactivity a breeze.

So I've asked myself: why not try to extract, broadly, this type of reactivity from VueJS? A few days later __OxJS__ was born.

# Epic music
__[OxJS](https://github.com/jfet97/oxjs)__ is a proof of concept library written in TS that enable encapsulated reactivity.

Let's try it to create an observable and a reactive object:

```js
const { ox } = require('oxjs');

// it creates an observable source
const $source = ox.observable({
    years: 32,
});

// it creates a reactive object
const reactiveObject = ox.observer(() => {
    // we are referencing the observable here
    const years = $source.years;

    // an object is returned
    // so we are creating a reactive object
    return {
        age: years,
    }
});

// initial evaluation
console.log(reactiveObject); // { age: 32 }

// we change the stored 'years' inside $source
$source.years = 28;

// the 'reactiveObject' is updated
console.log(reactiveObject); // { age: 28 }
```
As you can see the creation of both an observable and an observer is pretty straightforward; moreover the latter one is notified as soon as possible.
Obviously we are not limited to one observer for one observable at time: an observable can be used by any number of observers and an observer can use how many observable it needs.

# What about reactive primitives?
Here it is:
```js
const { ox } = require('oxjs');

// it creates two observable sources
const $source1 = ox.observable({
    years: 32,
});

const $source2 = ox.observable({
    name: 'Mario',
});

// it creates an observer that will behave as a string
const stringObserver = ox.observer(() => `My name is ${$source2.name} and I'm ${$source1.years} years old`);

// initial evaluation
console.log(`${stringObserver}`); // My name is Mario and I'm 32 years old

// we change the stored 'years' inside $source1
$source1.years = 28;

// the 'stringObserver' is updated
console.log(`${stringObserver}`); // My name is Mario and I'm 28 years old

// we change the stored 'name' inside $source2
$source2.name = 'Luigi';

// the 'stringObserver' is updated
console.log(`${stringObserver}`); // My name is Luigi and I'm 28 years old
```

As you will see my reactive primitives are not perfect, because they are not real primitives. Otherwise my API would not have been able to change the value referenced by them. In fact they are based on primitives wrappers and a weird ES6 Proxies hack that has got some limitations, due to the JS lang itself.

<img src="https://i.ibb.co/wSLcr7s/limited-JS.jpg" width="500"/>

But they are suitable for a wide range of cases if you pay a little attention. Most times you will not feel the difference. I hope.

# What's going on under the hood?
I'm not able to explain all the reactive hackish that I've proudly written, but I can try to describe the magic that happens when a reactive entity needs to be updated.

Let's suppose this is our source of truth:
```js
const $source = ox.observable({
    city: 'Carrara',
    country: 'Italy',
});
```

We call into question the following weird observer that could be either a `string` or an `object`:
```js
let weirdObserver = ox.observer(() => {
    const city = $source.city;
    const country = $source.country;

    if (city && city.length > 5) {
        return `${city} is located in ${country}`;
    } else {
        return {
            city,
            country
        }
    }
});

// initial evaluation
console.log(`${weirdObserver}`); // "Carrara is located in Italy"
```
Knowing that each time one of the used `$source` fields changes, the arrow function passed to `ox.observe` is called, the main problem was: how to change on what the `weirdObserver` identifier is pointing to?
Without relying on a closure, which would have led to a change in the way `ox.observe` and __OxJS__ were thought to be used, there is no way in JS.

Therefore, if we cannot move the `weirdObserver` identifier, we can't even set it to a primitive, because in JS two different identifiers cannot point to the same memory area if in it a primitive value is stored.

Wait a moment, why we need another reference?

Because if `weirdObserver` is immovable, we need another reference to the same thing pointed by it - reference that will be stored somehow by __OxJS__ - to perform the changes, so that `weirdObserver` "sees them" as well, so to speak.

To summarize what has been said so far:
* no primitives are allowed (here's why I do use primitive wrappers)
* `weirdObserver` is immovable and will always point to the same object
* there is another reference to the same object pointed by `weirdObserver` that is used to perform changes

Now another another problem comes up: that object should be able to completely change its nature. What if it should be transformed from an Array to a Number wrapper, to be then changed into a Promise, passing from a Map?
Yes I'm exaggerating, but I believe you have now grasped the point: there is no merge strategy nor prototypes hack which could help us.

So what? ES6 Proxies!

The solution I found is to return an almost fully transparent Proxy on which the target is dynamically changed at runtime. As a rule this is not possible, unless all traps are redirected.
I know, this is a big, ugly workaround. But I was able to made the hack resilient for the most use cases.

<img src="https://img.memecdn.com/trust-me-i-amp-039-m-an-engineer_o_1897979.jpg" width="400"/>

Returning to our example, the proxy referenced by `weirdObserver` will have a String wrapper as a target initially. Each time the source changes, even if the length limit is not exceeded, the target of the proxy will change.

If length of the new `$source.city` value is greater than 5, the new target will be a new String wrapper, otherwise will be a new `{ city, country }` object. Due to the nature of Proxies, the client, that is who use the `weirdObserver` identifier, will be able to use all the `String.prototype`'s methods in the former case and to perform almost all the operations which are allowed on an object in the latter.


# Other things that OxJS can do
I'm too lazy to create a clone of the README. Please check it out [here](https://github.com/jfet97/oxjs).

# Conclusion
As I said this library is only a proof of concept, IDK if this sort of reactivity could be suitable in real applications without having a framework that protect us. Maybe its "implicit" nature could quickly generate problems if misused.
I'd like to hear your opinion on that.

Moreover sometimes I like to develop only for the pleasure of it, without worrying too much on clean and efficient code nor wondering on real use cases of what I'm creating. This is one of those cases; I've focused more on trying to upgrade my TS skills (apparently with little success seeing how much I had to fight 😂) and on reaching my main goal: take reactivity to a greater level of mess.