# h-state

> Lightweight, Proxy-free state management for React. Mutate state directly
> (`store.count++`, `store.items.push(x)`) and components re-render automatically.
> Deep nested + array reactivity, vanilla (outside-React) subscriptions, one-line
> time travel (undo/redo), one-line cross-tab sync (BroadcastChannel), atomic
> transactions with automatic rollback, optional localStorage persistence with
> versioned migrations. Zero dependencies.

Key facts for assistants:
- Install: `npm install h-state`. React `>=16.8` peer dependency.
- Entry: `import { createStore, batch } from 'h-state'`.
- `createStore(initial, methodCreators, persistOptions?, storeOptions?)` returns `{ useStore, store }`.
- Time travel: pass `{ history: true }` as the 4th arg; use `store.$undo()`, `$redo()`, `$history()`.
- Cross-tab sync: pass `{ syncTabs: true }` as the 4th arg; `store.$destroy()` closes the channel.
- Atomic transactions: `store.$transaction(fn)` commits all mutations or rolls back if `fn` throws.
- Methods are creators: `(store) => (args) => void`.
- Tracked array methods: push, pop, shift, unshift, splice, sort, reverse, fill, copyWithin.
- NOT tracked: direct index assignment (`arr[0]=x`) and `arr.length=n` — use splice or reassign.

## Docs

- [Agent reference (exact API, patterns, mistakes)](https://github.com/HidayetCanOzcan/h-state/blob/master/AGENTS.md)
- [README (full guide)](https://github.com/HidayetCanOzcan/h-state/blob/master/README.md)
- [Live docs & demo](https://hidayetcanozcan.github.io/h-state)
- [npm package](https://www.npmjs.com/package/h-state)

## API surface

- `createStore(initial, methods, persistOptions?)` → `{ useStore, store }`
- `useStore()` / `useStore(selector, equalityFn?)`
- `store.$getState()`, `store.$subscribe(fn)`, `store.$subscribeWithSelector(sel, fn, eq?)`
- `store.$merge(partial)`, `store.$update()`, `store.$persist()`, `store.$clearPersist()`, `store.$reset()`
- `store.$undo()`, `store.$redo()`, `store.$history()`, `store.$clearHistory()` (requires `{ history: true }`)
- `store.$destroy()` (closes cross-tab channel; requires `{ syncTabs: true }`)
- `store.$transaction(fn)` (atomic; rolls back on throw, returns fn's result)
- `batch(fn)`
- Types: `PersistOptions`, `StoreType`, `MethodCreators`, `StoreOptions`, `HistoryOptions`, `HistoryState`, `SyncTabsOptions`
