States are callbags whose value can be manually modified:
1linkimport { state } from 'callbag-state';
2linkimport { pipe, subscribe } from 'callbag-common';
3link
4linkconst s = state(42);
5linkpipe(s, subscribe(console.log));
6link
7links.set(43);
8links.set(s.get() + 1);
42
43
44
1linkconst count = state(0);
2link
3linkrenderer.render(
4link <div>
5link { count }
6link  
7link <span onclick={() => count.set(count.get() - 1)}>⬇️</span>
8link <span onclick={() => count.set(count.get() + 1)}>⬆️</span>
9link </div>
10link).on(document.body);
👉 You can use .get()
method on any state to get its current value:
1linkconsole.log(s.get());
⚠️ IMPORTANT ⚠️
Don't change state objects without changing references:
1linkconst s = state([1, 2, 3, 4]);2link3link// 🚫 WRONG:4link/*~warn~*/s~.~get~~~(~)~.~push~~~~(~5~)~;~/*~warn~*/ // --> no updates5link6link// ✅ CORRECT:7links.set(s.get().concat([5]));8link9link// ✅ CORRECT:10links.set([...s.get(), 5]);11link12link// ✅😎 CORRECT & COOL:13links.sub(s.get().length).set(5); // @see [Substates](#substates)
When you store objects or arrays inside a state, use .sub()
to read/change their properties/indexes:
1linkconst dude = state({
2link name: 'John',
3link age: 32,
4link interests: [
5link 'programming',
6link 'painting',
7link ]
8link});
9link
10linkrenderer.render(
11link <>
12link Name:
13link <input type='text' _state={dude.sub('name')}/>
14link
15link Age:
16link <input type='number' _state={dude.sub('age')}/>
17link
18link Interests:
19link <input type='text' _state={dude.sub('interests').sub(0)}/>
20link <input type='text' _state={dude.sub('interests').sub(1)}/>
21link
22link <pre>{expr($ => JSON.stringify($(dude), null, 4))}</pre>
23link </>
24link).on(document.body);
☝️ .sub()
also returns a state, so you can use .get()
, .set()
and .sub()
on it recursively.
local_library FURTHER READING
States are directly exported from callbag-state, with special integrations with inputs and lists. Checkout docs of that library for more information.