はじめに
SynState は TypeScript/JavaScript 向けの軽量・高性能な状態管理ライブラリです。シンプルなグローバル状態から、debounce や switchMap を使った複雑な非同期パイプラインまで統一 API で記述できます。React Compiler と完全互換。
「SynState」は「Synchronized + State」に由来します。グリッチフリーな伝搬により、派生値は常に一貫した状態に保たれます — 不整合な中間状態は発生しません。(詳細: SynState がグリッチを解決した方法)
- 🎯 シンプルな状態管理: React の
useState/useReducerに似た使いやすいcreateStateとcreateReducer(グローバル状態向け)。 - ⚡ 高パフォーマンス: グリッチフリー 伝搬 — Jotai の約30倍、Redux の約16倍高速。ベンチマーク結果を参照。
- 🚀 軽量: ~4.5 kB min+gzip、外部ランタイム依存は ts-data-forge のみ。
- 🔧 非同期オペレーター内蔵:
debounce、throttle、switchMapなど — 複雑な非同期処理を外部ライブラリなしに統一的な宣言的 API で記述。 - ⚛️ React 最適化: React Compiler と完全互換。
synstate-react-hooksにより数行でコンポーネントにグローバル状態を導入。 - 🌐 フレームワーク非依存: コアはバニラ JavaScript、Vue、Svelte など任意のフレームワークでそのまま動作。React / Preact 向けには hooks ラッパー(
synstate-react-hooks/synstate-preact-hooks)、Preact 向けにはさらに Preact Signals 連携(synstate-preact-signals)も用意。
createState を1回呼ぶだけで、アプリケーションにグローバル状態を追加できます:
import { createState } from 'synstate';
// リアクティブな状態を作成const [state, setState] = createState(0);
// 変更を購読state.subscribe((count) => { console.log(count); // 0, 1});
// 状態を更新setState(1);createState はリアクティブな状態とセッター関数を作成します。サブスクライバーは初期値で即座に呼び出され、状態が更新されるたびに再び呼び出されます。
createState は3番目の要素として追加のユーティリティも返します:
const [ state, setState, { updateState, resetState, getSnapshot, initialState },] = createState(0);
updateState((prev) => prev + 1); // 前の値を使って更新resetState(); // 初期値(0)にリセットgetSnapshot(); // 現在の値を同期的に読み取り(0)initialState; // createState に渡した初期値(0)pipe で値を派生する
Section titled “pipe で値を派生する”SynState の力は Observable の合成にあります。pipe で新しい値を派生し、combine で複数のソースを結合します:
import { combine, createState, type InitializedObservable, map,} from 'synstate';
const [count, setCount] = createState<number>(0);
// 現在の値を取得console.log(count.getSnapshot().value); // 0
// pipe で新しい Observable を派生const doubled: InitializedObservable<number> = count.pipe(map((n) => n * 2));
// 複数の Observable を結合const combined: InitializedObservable<string> = combine([count, doubled]).pipe( map(([c, d]) => `(${c}, ${d})`),);
// 変更を購読count.subscribe((value) => { console.log('count:', value); // 0, 1, 2, 3});
doubled.subscribe((value) => { console.log('doubled:', value); // 0, 2, 4, 6});
combined.subscribe((value) => { console.log(value); // "(0, 0)", "(1, 2)", "(2, 4)", "(3, 6)"});
// 状態を更新setCount(1);setCount(2);setCount(3);この宣言的なモデルがどのように機能するか、なぜ命令的に状態を管理するよりも優れているかについては、宣言的な状態管理を参照してください。
React で使う
Section titled “React で使う”createState はモジュールスコープ(コンポーネントの外)で呼び出す必要があります。SynState は synstate-react-hooks というコンパニオンパッケージを提供しており、Observable と React を橋渡しします:
import type * as React from 'react';import { createState } from 'synstate-react-hooks';
const [useUserState, setUserState] = createState({ name: '', email: '',});
const UserProfile = (): React.JSX.Element => { const user = useUserState();
return ( <div> <p>{`Name: ${user.name}`}</p> <button onClick={() => { setUserState({ name: 'Alice', email: 'alice@example.com', }); }} > {'Set User'} </button> </div> );};詳細は React 連携を参照してください。
次のステップ
Section titled “次のステップ”- インストール — SynState とオプションのコンパニオンパッケージをインストール。
- SynState の強み — 設計思想、グリッチフリー保証、ユースケース。
- 宣言的な状態管理 — 具体的な例でリアクティブプログラミングモデルを理解する。
- React 連携 — SynState を React で使う。