Skip to content

nexa-reactivity

The core reactivity package providing Signals, computed values, effects, batching, and untracked reads.

signal

Creates a reactive value with automatic dependency tracking.

ts
import { signal } from 'nexa-reactivity'

function signal<T>(initial: T): Signal<T>

Signal<T>

ts
interface Signal<T> {
  get value(): T
  set value(val: T)
  peek(): T
  toJSON(): T
}
MemberDescription
valueGetter triggers tracking; setter triggers subscribers
peek()Read current value without creating a dependency
toJSON()Returns value for JSON serialization

Examples:

ts
const count = signal(0)
count.value = 1
console.log(count.value)     // 1
console.log(count.peek())    // 1 (no tracking)
console.log(JSON.stringify({ count })) // {"count":1}

computed

Derives a value from signals with lazy evaluation and caching.

ts
import { computed } from 'nexa-reactivity'

function computed<T>(fn: () => T): Signal<T>

Returns a read-only Signal<T> whose value is lazily recomputed only when dependencies change.

Example:

ts
const a = signal(2)
const b = signal(3)
const sum = computed(() => a.value + b.value)
console.log(sum.value) // 5
a.value = 10
console.log(sum.value) // 13

effect

Runs a function whenever its tracked signal dependencies change.

ts
import { effect } from 'nexa-reactivity'

function effect(fn: () => void | (() => void)): () => void

Returns a dispose function. If fn returns a function, that cleanup is called before re-execution or disposal.

Examples:

ts
const dispose = effect(() => {
  console.log(count.value)
})
// Later:
dispose()

// With cleanup
effect(() => {
  const id = setInterval(() => {}, 1000)
  return () => clearInterval(id)
})

batch

Groups multiple signal writes, triggering effects only once after all writes complete.

ts
import { batch } from 'nexa-reactivity'

function batch(fn: () => void): void

Example:

ts
const x = signal(1)
const y = signal(2)

effect(() => console.log(x.value + y.value))
// Logs: 3

batch(() => {
  x.value = 10
  y.value = 20
})
// Logs: 30 (only once)

untracked

Reads signals inside fn without creating tracking dependencies.

ts
import { untracked } from 'nexa-reactivity'

function untracked<T>(fn: () => T): T

Example:

ts
const a = signal(1)
const b = signal(2)

effect(() => {
  console.log(a.value)         // tracks a
  console.log(untracked(() => b.value)) // does not track b
})

Released under the MIT License.