Skip to content

Reactive signals with computed values, effects, and batching. Zero deps. TypeScript-first.

License

Notifications You must be signed in to change notification settings

corvid-agent/signal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@corvid-agent/signal

Reactive signals with computed values, effects, and batching. Zero deps. TypeScript-first.

Install

npm install @corvid-agent/signal

Usage

import { signal, computed, effect, batch } from "@corvid-agent/signal";

// Writable signal
const count = signal(0);
console.log(count.value); // 0

// Computed (derived) signal
const doubled = computed(() => count.value * 2);
console.log(doubled.value); // 0

// Effect — runs immediately and re-runs when dependencies change
const dispose = effect(() => {
  console.log("doubled is", doubled.value);
});
// logs: "doubled is 0"

count.value = 5;
// logs: "doubled is 10"

// Batch — defer effects until all updates are applied
batch(() => {
  count.value = 1;
  count.value = 2;
});
// logs once: "doubled is 4"

// Stop listening
dispose();

API

signal<T>(initialValue: T, options?): WritableSignal<T>

Create a writable reactive signal.

  • .value — get/set the current value (tracks dependencies on read)
  • .peek() — read without tracking

Options:

  • equals — custom equality function (default: Object.is)

computed<T>(fn: () => T, options?): ReadonlySignal<T>

Create a read-only derived signal. Re-evaluates lazily when dependencies change.

  • .value — get the derived value (tracks dependencies)
  • .peek() — read without tracking

Options:

  • equals — custom equality function (default: Object.is)

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

Create a side effect that runs whenever its dependencies change. Runs immediately on creation.

The effect function may return a cleanup function, which is called before each re-run and on disposal.

Returns a Dispose function to stop the effect.

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

Batch multiple signal updates. Effects only run once after all updates are applied. Supports nesting.

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

Run a function without tracking signal reads as dependencies.

Features

  • Automatic dependency tracking — no manual subscriptions
  • Lazy evaluation — computeds only recompute when read
  • Batching — group updates to minimize effect re-runs
  • Cleanup — effects support cleanup functions
  • Circular dependency detection — throws on circular computeds
  • Dynamic dependencies — tracks only what's actually read each run
  • Custom equality — control when updates propagate
  • Zero dependencies

License

MIT

About

Reactive signals with computed values, effects, and batching. Zero deps. TypeScript-first.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors