Installation
npm add synstateOr with other package managers:
# Yarnyarn add synstate
# pnpmpnpm add synstateReact Hooks
Section titled “React Hooks”If you are using React, install the companion hooks package:
npm add synstate-react-hookssynstate-react-hooks includes all exports from synstate plus the createState, createReducer, and createBooleanState APIs extended for React, so you don’t need to add synstate along with it.
React Hooks (React 16.8–17)
Section titled “React Hooks (React 16.8–17)”For React 16.8–17 (without useSyncExternalStore), use the compat package instead:
npm add synstate-react-hooks-compatThe API is identical to synstate-react-hooks. See React Integration for details.
Preact Hooks
Section titled “Preact Hooks”If you are using Preact, install the companion hooks package:
npm add synstate-preact-hooksPreact Signals
Section titled “Preact Signals”To render with Preact Signals instead of hooks, install the bridge package together with its peer dependencies, preact and @preact/signals:
npm add synstate-preact-signals preact @preact/signalsIt converts between Observables and signals (toSignal, fromSignal), and its createState, createReducer and createBooleanState return a ReadonlySignal instead of a hook. Like the hooks packages, it re-exports the functions and types of synstate. See the Preact Signals demo.
synstate-dom (no framework)
Section titled “synstate-dom (no framework)”synstate-dom is a compiler-free UI library built on SynState that binds Observables directly to the DOM, with no virtual DOM and no framework. Introducing synstate-dom shows it with live demos; its installation and API are on its own documentation site.
ESLint plugin
Section titled “ESLint plugin”eslint-plugin-synstate reports mistakes that the types cannot catch, such as a write to a state from a subscriber (synstate/no-write-during-propagation, see A write from a subscriber). It needs ESLint 9 or later, with a flat config:
npm add -D eslint-plugin-synstateIts recommended preset registers the plugin and turns on every rule. The rules need no type information; when your config already lints with it (parserOptions.projectService), no-write-during-propagation also follows setters imported from other files:
// eslint.config.mtsimport { eslintPluginSynstate } from 'eslint-plugin-synstate';
export default [eslintPluginSynstate.configs.recommended];The rules and how to configure them one by one are in the plugin’s README.