Index
State Management
Section titled “State Management”SynState provides simple, intuitive APIs for managing application state:
createState: Create state withInitializedObservableand setter.createReducer: Create state by reducer and initial value.createBooleanState: Specialized state for boolean values.
Event System
Section titled “Event System”Built-in event emitter for event-driven patterns:
createValueEmitter: Create type-safe event emitters.createEventEmitter: Create event emitters without payload.
Observable APIs
Section titled “Observable APIs”For complex scenarios, SynState provides observable-based APIs:
Creation Functions
Section titled “Creation Functions”source<T>(): Create a new observable source (almost equivalent to RxJSsubject).just(value): Create an Observable that holds a single static value and immediately completes. Useful as a synchronous fallback insideswitchMap.empty(): Create an Observable that holds no value and is already completed (almost equivalent to RxJSEMPTY). Useful for the branch of aswitchMapthat should follow nothing.fromPromise(promise): Create observable from promise.fromAbortablePromise(factory): Create observable from a promise factory that receives anAbortSignal, aborted when the observable completes (as whenswitchMapswitches away).fromSubscribable(): Create observable from any subscribable object.counter(ms): Emit 0 at once, then 1, 2, … at intervals (almost equivalent to RxJStimer(0, ms); with{ emitInitial: false }, almost equivalent tointerval(ms);{ times: n }completes it afternvalues).timer(delay): Emit after delay.
Combination
Section titled “Combination”combine(observables): Combine latest values from multiple sources (alias:combineLatest).derive(observables, fn): Derive one value from the latest values of multiple sources, as one observable.merge(observables): Merge multiple streams.zip(observables): Pair values by index.
Operators
Section titled “Operators”map variants
Section titled “map variants”map(fn): Transform values.mapTo(value): Map all values to a constant.getKey(key): Extract property value from objects (alias:pluck).attachIndex(): Attach index to each value (alias:withIndex).
Result/Optional
Section titled “Result/Optional”mapOptional(fn): Map over Optional values.mapResultOk(fn): Map over Result ok values.mapResultErr(fn): Map over Result error values.unwrapOptional(): Unwrap Optional values to undefined.unwrapResultOk(): Unwrap Result ok values to undefined.unwrapResultErr(): Unwrap Result error values to undefined.
Flat map
Section titled “Flat map”mergeMap(fn): Map to observables and merge all (runs in parallel) (alias:flatMap).switchMap(fn): Map to observables and switch to latest (cancels previous).
Filtering
Section titled “Filtering”filter(predicate): Filter values.skipIfNoChange(): Skip duplicate values (alias:distinctUntilChanged).skip(n): Skip first n emissions.take(n): Take first n emissions then complete.skipWhile(predicate): Skip values while predicate is true.takeWhile(predicate): Emit values while predicate is true, then complete.skipUntil(notifier): Skip values until notifier emits.takeUntil(notifier): Complete on notifier emission.
Time series processing
Section titled “Time series processing”audit(ms): Emit the last value after specified time window (almost equivalent to RxJSauditTime).debounce(ms): Debounce emissions (almost equivalent to RxJSdebounceTime).throttle(ms): Throttle emissions (almost equivalent to RxJSthrottleTime).
Others
Section titled “Others”pairwise(): Emit previous and current values as pairs.scan(reducer, seed): Accumulate values.withBuffered(observable): Buffer values from observable and emit with parent (alias:withBufferedFrom).withCurrentValueFrom(observable): Sample current value from another observable (alias:withLatestFrom).withInitialValue(value): Provide an initial value for uninitialized observable.keepEqualParts(options?): Keep the parts equal to the last value and skip a value equal to it as a whole (structural sharing). Prefer thekeepEqualPartsoption ofcreateStatefor a state you write.
Scopes (for library authors)
Section titled “Scopes (for library authors)”For libraries built on SynState, such as a UI binding that mounts and unmounts parts of a page. Application state defined at module level belongs to no scope and needs none of this.
createScope(parent?, { after? }): Create a scope. Observables created synchronously insidescope.run(body)belong to it, andscope.dispose()disposes them without completing the shared observables they were derived from. Asubscribemade there belongs to it too, anddispose()unsubscribes it. Withparent, it is disposed together with the parent. Withafter, every observable derived in the scope and its child scopes updates afterafter, however few steps it is from the source; a switch that mounts a branch in the scope passes the value it switches on, so that it disposes a branch the next value rules out before the branch computes that value.getCurrentScope(): The scope whoserunis executing, if any. Take it while still synchronous and wrap work after anawaitin itsrun, since only what is created synchronously joins a scope.onScopeDispose(cleanup): Callcleanupwhen the current scope is disposed.untracked(body): Callbodywith no current scope, so that what it creates, and what it subscribes, outlives the surrounding scope.
dispose() ends the subscriptions, then disposes the child scopes, then calls the onScopeDispose functions, then disposes the owned observables, each newest first. A subscription made in the scope therefore hears neither a value an onScopeDispose function writes nor the completion of the observables the scope or its children dispose. An update or a completion runs in no scope, whichever scope wrote the value or completed the observable, so what a subscriber subscribes or creates on hearing it belongs to no scope unless the subscriber runs one. run on a disposed scope warns and owns nothing it creates.
Utilities
Section titled “Utilities”isChildObservable(obs): Check if observable is a child observable.isManagerObservable(obs): Check if observable is a manager observable.isRootObservable(obs): Check if observable is a root observable.
Framework Integration
Section titled “Framework Integration”React / Preact Hooks (synstate-react-hooks / synstate-preact-hooks)
Section titled “React / Preact Hooks (synstate-react-hooks / synstate-preact-hooks)”Both packages share the same API surface. Use synstate-react-hooks for React 18+ and synstate-preact-hooks for Preact.
useObservableValue(observable$): Subscribe to an observable and return its current value as component state. UsesuseSyncExternalStoreinternally — the component re-renders when the observable emits.useObservableValue(observable$, fallback): Same as above, with a fallback value for observables without an initial value.useObservableEffect(observable$, fn): Subscribefnwhile the component is mounted (details).useValueAsObservable(value): Convert a component prop/state value into a synstate observable. Useful for bridging React/Preact state into the observable graph. The observable completes when the component unmounts. In React, it is replaced after an<Activity>is hidden and shown again, so read it from each render rather than keeping the first one.
State Wrappers
Section titled “State Wrappers”These re-export core createState / createReducer / createBooleanState but return a hook (useCurrentValue) as the first tuple element instead of the raw observable:
createState(initialValue): Returns[useCurrentValue, setState, { state, updateState, resetState, getSnapshot, initialState }].createReducer(reducer, initialState): Returns[useCurrentValue, dispatch, { state, getSnapshot, initialState }].createBooleanState(initialValue): Returns[useCurrentValue, { state, setTrue, setFalse, toggle, setState, updateState, resetState, getSnapshot, initialState }].
Preact Signals (synstate-preact-signals)
Section titled “Preact Signals (synstate-preact-signals)”Bridges synstate observables with Preact Signals for fine-grained DOM updates without component re-renders. See the interactive demo to compare with the hooks approach.
Bridge Functions
Section titled “Bridge Functions”toSignal(observable$): Convert anObservable(orInitializedObservable) into a PreactReadonlySignal. The signal stays in sync with the observable. Can be embedded directly in JSX — only the affected text node updates, not the entire component.toSignal(observable$, fallback): Same as above, with a fallback value for observables without an initial value.fromSignal(signal): Convert a PreactSignalinto a synstateInitializedSourceObservable. Returns[observable, dispose]. The observable mirrors the signal’s value, enabling the full synstate operator chain (map,debounce,switchMap, etc.).
State Wrappers
Section titled “State Wrappers”Same as the hooks wrappers, but return a ReadonlySignal instead of a hook:
createState(initialValue): Returns[signal, setState, { state, updateState, resetState, getSnapshot, initialState }].createReducer(reducer, initialState): Returns[signal, dispatch, { state, getSnapshot, initialState }].createBooleanState(initialValue): Returns[signal, { state, setTrue, setFalse, toggle, setState, updateState, resetState, getSnapshot, initialState }].