Expressive State
API Reference

Utilities

Framework-agnostic helpers - watch, listener, event, Context, Observable

These exports are framework-agnostic. They're available from both @expressive/state and @expressive/react.

import { watch, listener, event, Context, Observable, unbind } from '@expressive/state';

watch(target, callback)

Subscribe to a State's tracked values from outside a framework. Equivalent to state.get(effect) but as a free function.

import { watch } from '@expressive/state';

const state = Counter.new();

const stop = watch(state, (current) => {
  console.log('count:', current.count);
});

state.count++;
stop();

Signature:

function watch<T>(target: T, callback: Effect<T>, recursive?: boolean): () => void;
function watch<T>(target: T, callback: Effect<Required<T>>, requireValues: true): () => void;

Pass requireValues: true to throw on undefined tracked values - useful when the effect assumes all data is present.


listener(target, callback, select?)

Low-level listener for an observable's event stream. Receives every signal (property updates, lifecycle events, custom events).

import { listener } from '@expressive/state';

const stop = listener(state, (key, source) => {
  if (key === true) console.log('ready');
  else if (key === false) console.log('batch settled');
  else if (key === null) console.log('destroyed');
  else console.log('event:', key);
});

Optionally filter by a specific signal or a set of signals.


event(target, key?, silent?)

Dispatch an event on a State manually. Equivalent to state.set(key) but available as a free function.

event(state, 'my-event');
event(state, Symbol.for('refresh'));

Context

The context system that backs Provider and the get instruction.

import { Context } from '@expressive/state';

const ctx = new Context({ AppState, UserState });
const app = ctx.get(AppState);
const child = ctx.push({ ChildState });
child.pop();
MethodDescription
Context.rootRoot context - global fallback
Context.get(s?)Get the context for a given state
ctx.get(Type)Look up a state by type (upstream)
ctx.set(input, forEach?)Register states in the context
ctx.push(input?)Create a child context
ctx.pop()Destroy this context and its registered states

Adapters can override Context.get to provide framework-specific context (as the React adapter does).


Observable

Base type that State extends. You rarely need to interact with Observable directly - it's exposed mainly for tooling and advanced use cases.

import { Observable } from '@expressive/state';

Observable is also a unique symbol used as a protocol key on objects that participate in the event system.


unbind(fn)

Return the original, unbound version of a method. Expressive auto-binds methods on first access; unbind gives you the raw function if you need it (for e.g. composing with other function wrappers).

import { unbind } from '@expressive/state';

const raw = unbind(state.someMethod);

Re-exports

@expressive/react re-exports everything from @expressive/state:

import State, {
  Component,
  Provider,
  Consumer,
  Context,
  Observable,
  def,
  event,
  get,
  listener,
  ref,
  set,
  unbind,
  watch,
} from '@expressive/react';

So a React project never needs to import from @expressive/state directly.

On this page