1.0.8 • Published 1 year ago

nonr v1.0.8

Weekly downloads
-
License
MIT
Repository
-
Last release
1 year ago

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   
};