Refs Guide
See also: Refs API
Refs lend themselves extremely well to reactive GUI programming.
This guide explains how they work and shows some basic recipes.
Basics
A ref is like a pointer.
const r = $(0)
console.log('val is', r.val) // val is 0
r.val++
console.log('val is', r.val) // val is 1
You can watch it.
const r = $(0)
r.watch(n => console.log('val is', n))
r.val = 3 // val is 3
r.val++ // val is 4
You can adapt it to another value.
const r = $(0)
const r2 = r.adapt(n => n * 2)
r2.watch(n => console.log('val is', n))
r.val = 3 // val is 6
r.val++ // val is 8
Properties
You can back existing properties with a ref.
const point = { x: 0, y: 0 }
const $x = makeRef(point, 'x')
$x.watch(x => console.log('val is', x))
point.x = 10 // val is 10
point.x++ // val is 11
You can even back class properties.
class Point {
x = 0
y = 0
$x = makeRef(this, 'x')
$y = makeRef(this, 'y')
}
const point = new Point()
point.$x.watch(x => console.log('val is', x))
point.x = 10 // val is 10
point.x++ // val is 11
Advanced
You can create a new ref based on multiple other refs:
const r1 = $(1)
const r2 = $(100)
const r3 = multiplex([r1, r2], (v1, v2) => v1 * v2)
console.log(r3.val) // 100
r3.watch(n => console.log(`${r1.val} * ${r2.val} = ${n}`))
r1.val++ // 2 * 100 = 200
r1.val++ // 3 * 100 = 300
r2.val *= 2 // 3 * 200 = 600
You can change a value before watchers see it.
This is useful for normalizing/constraining values.
const r = $(0)
r.watch(n => console.log('val is', n))
r.intercept(n => Math.max(0, Math.min(10, n)))
r.val = 9 // val is 9
r.val++ // val is 10
r.val++ // (nothing printed; no change in value)
console.log('val is currently', r.val) // val is currently 10
You can make one ref defer to another.
This basically ties the two refs together.
const first = $(10)
first.watch(n => console.log('first is', n))
console.log(first.val) // 10
const second = $(0)
first.defer(second) // first is 0
first.val++ // first is 1
second.val++ // first is 2
console.log(first.val) // 2
console.log(second.val) // 2
second.watch(n => console.log('second is', n))
first.val++ // first is 3
// second is 3
second.val++ // first is 4
// second is 4