Mikata

Reactivity

@mikata/reactivity is the signal runtime the rest of the framework is built on. There are three primitives: signals, computeds, and effects.

Signals

A signal holds a value and tracks every read. Call the getter to read; call the setter to write.

import { signal } from '@mikata/reactivity';

const [count, setCount] = signal(0);

count();          // 0
setCount(1);
count();          // 1
setCount((n) => n + 1);
count();          // 2

Computed

computed returns a read-only getter whose value is derived from other signals. It only re-runs when a read dependency changes, and it's memoized - reading a computed twice in a row doesn't recompute.

import { signal, computed } from '@mikata/reactivity';

const [items, setItems] = signal<number[]>([1, 2, 3]);
const total = computed(() => items().reduce((a, b) => a + b, 0));

total();          // 6
setItems([1, 2, 3, 4]);
total();          // 10

Effects

Effects run side effects when their tracked signals change. They run once on creation, then again whenever a dependency fires.

import { signal, effect } from '@mikata/reactivity';

const [name, setName] = signal('world');

effect(() => {
  console.log('hello,', name());
});

setName('mikata');
// logs: hello, mikata

Batching

Multiple writes inside batch() collapse into a single notification, so effects run once with the final state.

import { signal, effect, batch } from '@mikata/reactivity';

const [a, setA] = signal(1);
const [b, setB] = signal(2);

effect(() => console.log(a() + b()));
// logs: 3

batch(() => {
  setA(10);
  setB(20);
});
// logs once: 30 - not twice