nonr v1.0.8
nonr
Non-R is a minimal state management library.
The output of a function depends on the objects used in the computation. These are known as the dependents of the function. Note that a function may be a dependent of another function.
Nonr is used to link a function with its dependents so that if any dependent changes its value, then the function will recompute its own value.
Installation and import
Install:
npm i nonr
yarn add nonr
Import:
import {nonr} from 'nonr'
const {nonr} = require('nonr').default
From mobx to nonr
If you are coming from mobx, then you may be familiar with the @observable
and @computed
mechanisms:
class Proto {
@observable value = 0
@computed get valueAsString() {
return value.toString()
}
}
const obj = new Proto()
autorun(() => {
console.log(obj.valueAsString)
})
If Proto
were to be instantiated as an object,
then changes to the value
would cause any functions observing it to recompute.
valueAsString
is one such function,
and in turn, there is an autorun-wrapped function which is observing valueAsString
,
and this will also recompute in response to valueAsString
recomputing.
This how the mobx example above would be translated to nonr:
const obj = nonr({
value: 0
})
const valueAsString = nonr(() => {
return obj.value.toString()
})
nonr(() => {
console.log(valueAsString())
})
Nonr is ubiquitous. Nonr is everywhere.
Nonr rules
The only things that can be wrapped are objects and functions:
const na = nonr([])
const no = nonr({})
const nf = nonr(() => {})
How do I make changes propagate? Nonr links functions calls together so that downstream changes cause upstream changes. Calling the getter of an object causes updates. Only things decorated with nonr can cause upstream changes.
const obj = nonr({
value: 0
})
const nf1 = nonr(() => {
const value = obj.value
console.log('nf1', value)
return value
})
const nf2 = nonr(() => {
const value = nf1() + 1
console.log('nf2', value)
return value
})
const nf3 = nonr(() => {
const value = nf2() + 1
console.log('nf3', value)
return value
})
console.log('setup done')
obj.value = 1
// prints:
// nf1 0
// nf2 1
// nf3 2
// setup done
// nf1 1
// nf2 2
// nf3 3
How do I make something change in response to a button press? Fine grained DOM updates are possible with nonr:
<body>
<script type="module">
import {nonr} from 'https://unpkg.com/nonr/dist/nonr.mjs'
const valueSpan = document.getElementById('value')
const store = nonr({value: 0})
nonr(() => {
valueSpan.innerHTML = store.value.toString()
})
window.add = () => {
store.value++
}
window.sub = () => {
store.value--
}
</script>
<span id="value">0</span>
<button onclick="sub()">-</button>
<button onclick="add()">+</button>
</body>
Try the code above: https://unpkg.com/nonr/examples/fine-grained-reactivity.html
API
export {
nonr, // converts input into a proxy
isNonr, // checks if something was wrapped with nonr
fromPromise, // allows nonr functions to react to promises
hasDependent, // a isDependent on b
getDependents, // list of nonr objects and functions
getCreationContext // useful for checking identity
};