Literals and stores
There are two ways to store data when working with ceres: literals and stores.
Literals
Any JavaScript variable that can be represented as a string is a literal. Literals can be used to set attributes or as children. When a literal appears as a child of an element, it will be rendered as a text node. It’s important to know that literals are not reactive, so changing the value of a literal after it has rendered has no effect.
const name = "Ceres Fauna";
let graduated = true;
$element("div", {},
$element("span", {}, name),
$element("button", { disabled: graduated }, "Watch")
)
.mount(document.body);
// Does nothing.
graduated = false;
Stores
Stores hold a literal and can be subscribed to. Whenever the stored value changes all subscribers will be notified. You can create a store by calling $store
with an initial value. Reading and writing to a store is done through the value
property. If necessary, you can specify the type of the store at creation.
const graduated = $store(true);
graduated.value = false;
console.log(graduated.value);
const nullable = $store<string | null>(null);
Stores can be used in place of literals, but they are reactive and renderables will update when their values change.
const name = "Ceres Fauna";
const graduated = $store(true);
$element("div", {},
$element("span", {}, name),
$element("button", { disabled: graduated }, "Watch")
)
.mount(document.body);
// Now it works!
setTimeout(() => graduated.value = false, 1000);
Embedding stores on strings
Stores may be used to construct reactive strings using the $format
tag.
const pi = $store(3.1415926535897932384);
$element("span", {}, $format`PI = ${pi}`)
.mount(document.body);
setTimeout(() => pi.value = 3, 1000);
Derived stores
Stores can be transformed to create a new store that updates whenever the original changes. To create a derived store call derive
on the original store, and give it a transformation function. The original store is unaffected.
const pi = $store(3.1415926535897932384);
const tau = pi.derive((pi) => 2 * pi);
$element("span", {}, $format`TAU = ${tau}`)
.mount(document.body);
To combine multiple stores, use the $derive
function with the original stores, along with an aggregator function.
const baseDamage = $store(2);
const critMultiplier = $store(1.5);
const critDamage = $derive([baseDamage, critMultiplier], ([base, multi]) => base * multi);
Custom stores
You can write your own stores by extending the Store
class, and ceres will know how to make them reactive. It just works.
class Hakos extends Store<number> {
private stored: number;
constructor() {
super();
setInterval(() => this.value = Math.random(), 1000);
this.stored = Math.random();
}
get value() { return this.stored };
set value(value) {
const previous = this.value;
this.stored = value;
this.notify(previous);
}
}
const baelz = new Hakos();
$element("span", {}, baelz).mount(document.body);