Transaction-first state for React
Every state change is a transaction. Optimistic UI, rollback, retry, undo/redo, time travel, routing, forms, persistence, cross-tab sync — all automatic. Zero dependencies. One mesh.
One store for everything. State, server cache, forms, URL parameters, routing, cross-tab sync, undo history — all live in one store with one set of types. No more wiring together 5 libraries with different mental models.
Every state change is a transaction. Validate, optimistic update, effect, commit, rollback — all automatic. Retry with exponential backoff, timeout, and cancellation.
Subscriptions that never waste renders. Path-scoped selectors with equality checking. Updating cart.items does not rerender components reading theme.
Zero runtime dependencies. React is the only peer dependency.
npm install statemesh-coreimport { createMesh, StateMeshProvider, useMeshState } from "statemesh-core";
const mesh = createMesh({
state: { count: 0 }
});
function Counter() {
const [count, setCount] = useMeshState<number>("count");
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
export function App() {
return (
<StateMeshProvider mesh={mesh}>
<Counter />
</StateMeshProvider>
);
}| Feature | What it does |
|---|---|
| State | External store with path-based subscriptions, useSyncExternalStore |
| Actions | Named state mutations with payloads and handlers |
| Selectors & Computed | Derived state, memoization, dependency tracking |
| Transactions | Async lifecycle — validate, optimistic, effect, commit, rollback |
| Undo / Redo | Automatic history tracking with configurable depth |
| Time Travel | Replay to any point in time |
| Middleware Pipelines | Intercept, transform, log, and guard state changes |
| Resources | Cached API reads with deduplication, polling, pagination |
| Mutations | Write operations with optimistic rollback and offline queue |
| API Client | Built-in HTTP client with interceptors and retry |
| Persistence | localStorage, sessionStorage, IndexedDB, cross-tab sync |
| Forms | Async validation, schema adapters, field arrays, autosave |
| URL State | Sync state with URL search params |
| Router | Routing IS state management — transactions, loaders, guards |
| DevTools | Timeline, profiler, diagnostics, state inspector |
| Testing | Mock helpers, assertions, async utilities |
const checkout = mesh.transaction("cart.checkout", {
optimistic(state) {
state.cart.status = "processing";
},
async effect(state, payload, ctx) {
return fetch("/api/checkout", { signal: ctx.signal });
},
commit(state, result) {
state.order = result;
state.cart.items = [];
},
rollback: true,
retry: { attempts: 3, delay: backoff() }
});function CheckoutButton() {
const tx = useMeshTransaction(checkout);
return (
<button disabled={tx.pending} onClick={() => tx.run({ paymentMethodId: "card_1" })}>
{tx.pending ? "Processing..." : "Pay now"}
</button>
);
}const routes = defineRoutes([
{
path: "/products",
component: () => import("./pages/Products"),
loader: ({ mesh }) => mesh.resource("products.list").fetch(),
children: [
{
path: ":id",
component: () => import("./pages/ProductDetail"),
loader: ({ params, mesh }) => mesh.resource("product.detail").fetch({ id: params.id })
}
]
}
]);function Layout() {
return (
<div>
<nav>
<Link to="/products">Products</Link>
</nav>
<Outlet />
</div>
);
}Full documentation is available at react-statemesh.github.io/statemesh-docs
| Section | What's covered |
|---|---|
| Guide | Installation, core concepts, TypeScript |
| Core | State, actions, selectors, transactions, undo/redo |
| Data | Resources, mutations, API client, persistence |
| UI | Forms, URL state, error boundaries |
| Router | Routes, navigation, guards, data loading, SEO |
| Advanced | Middleware, guards, plugins, sync, devtools |
| Testing | Test helpers and patterns |
| Integration | Next.js, migration from other libraries |
| API Reference | Error codes, events, changelog |
603 tests across 19 test files covering every module, API surface, error path, and edge case.
pnpm test # Full suite
pnpm test:types # Type tests only
pnpm test:watch # Watch mode- Zero runtime dependencies — React is a peer dependency
- 100% TypeScript — type-safe paths, discriminated events, generic inference
- SSR-safe — all browser APIs guarded, dehydrate/hydrate for server rendering
- Tree-shakeable — router, devtools, and testing are separate entry points
- Bounded memory — LRU caches, ring buffers, snapshot limits