// Listen to any item title changeconst off = store.connect( { reducer: 'todos', property: 'items.*.title' }, (chg) => console.log('some title changed'));
Emits a typed event (channel, type, payload).
Events are queued and processed **sequentially** (FIFO).
**Pipeline per event:** the *reduce phase* (steps 1-4) runs **synchronously**,
so getState() reflects the change as soon as emit() returns; the *effect
phase* (step 5) runs afterwards, asynchronously.
1. **Deduplication** (opt-in) - Skip when content-dedup is enabled (dedupWindowMs > 0) or a matching dedupKey recurs; off by default
2. **Middleware** (sync) - Pre-reducer hooks; may cancel by returning false
3. **Reducers** (sync) - state updates + fine-grained path notifications
4. **Subscribers + coarse** (sync) - event subscribers (fire-and-forget) then coarse listeners (only if state changed)
5. **Effects** (async) - side-effects keyed by (channel, type); the returned promise resolves once they complete
**Change Detection**: Uses reference equality (===) on this.state to determine
if any slice changed. Works because forwardEvent creates a new state reference
via shallow spread when any slice changes.
Subscribe to events by channel and type.
Event subscriptions are intended for the View layer (e.g., React components)
to react to events without affecting the event flow. They are fire-and-forget
and cannot cancel event propagation.
**Phases:**
- 'committed' (default): Events that passed middleware and reached reducers.
Notified after reducers, before effects.
- 'uncommitted': Events rejected by middleware. Notified immediately after rejection.
- 'all': Both committed and uncommitted events. Handler receives the phase parameter
to distinguish between the two.
Subscribe to events by channel and type.
Event subscriptions are intended for the View layer (e.g., React components)
to react to events without affecting the event flow. They are fire-and-forget
and cannot cancel event propagation.
**Phases:**
- 'committed' (default): Events that passed middleware and reached reducers.
Notified after reducers, before effects.
- 'uncommitted': Events rejected by middleware. Notified immediately after rejection.
- 'all': Both committed and uncommitted events. Handler receives the phase parameter
to distinguish between the two.
Registers an **effect** (stateless async event consumer) that runs after reducers.
Effects are **keyed** by (channel, type) for O(1) lookup (no scanning all effects).
signature
registerEffect(spec): () => void
Registers an **effect** (stateless async event consumer) that runs after reducers.
Effects are **keyed** by (channel, type) for O(1) lookup (no scanning all effects).
Subscribes to **coarse-grained** commits (called once per successful event, only if state changed).
**Use Case**: React's useSyncExternalStore or similar external store integrations.
signature
subscribe(fn): () => void
Subscribes to **coarse-grained** commits (called once per successful event, only if state changed).
**Use Case**: React's useSyncExternalStore or similar external store integrations.
Parameters
Name
Type
Description
fn
() => void
Listener invoked after reducers/effects have run and state has changed.
Returns
() => void — Unsubscribe function.
Example
example
const off = store.subscribe(() => console.log('state committed'));// Later:off();