State
The mesh holds your application state as a plain JavaScript object. You read it, write it, and subscribe to changes.
Read State
// Get the full state object
const state = mesh.getState();
// Read a specific path
import { getPath } from "statemesh-core";
const theme = getPath(state, "theme");
const itemCount = getPath(state, "cart.items.length");Write State
// Replace the full state
mesh.setState({ theme: "dark", cart: { items: [], count: 0 } });
// Update a single path
mesh.setPath("theme", "dark");
mesh.setPath("cart.count", 5);
mesh.setPath("user.address.city", "New York");setPath accepts dot-separated paths and creates intermediate objects as needed. The path "user.address.city" will create user.address if it doesn't exist.
Reset State
// Reset to the initial state provided to createMesh
mesh.reset();If undo/redo is enabled, reset() pushes the pre-reset state to the undo stack so the user can undo the reset.
Destroy
// Clean up all subscriptions, plugins, timers, and resources
mesh.destroy();WARNING
After calling destroy(), the mesh instance is unusable. Any further calls to getState(), setState(), subscribe(), etc. will throw.
Subscribe
Subscriptions let you react to state changes. You provide a selector (to extract a piece of state) and a callback (that runs when the selected value changes).
Basic Subscription
const unsubscribe = mesh.subscribe(
(state) => state.theme,
(theme) => console.log("Theme changed to:", theme)
);
// Later: stop listening
unsubscribe();Path-Based Subscription (React)
In React, use useMeshState or useMeshSelector for path-based subscriptions:
import { useMeshState, useMeshSelector } from "statemesh-core";
function ThemeDisplay() {
const [theme, setTheme] = useMeshState<"light" | "dark">("theme");
return <span>{theme}</span>;
}
function CartBadge() {
const count = useMeshSelector((state) => state.cart.items.length);
return <span>{count} items</span>;
}Equality Functions
By default, subscriptions compare values by reference. You can provide a custom equality function:
import { shallowEqual } from "statemesh-core";
mesh.subscribe(
(state) => ({ theme: state.theme, lang: state.lang }),
(value) => console.log("Theme or lang changed:", value),
shallowEqual
);The shallowEqual function compares each property of the selected object by reference. StateMesh also exports cloneState for deep cloning.
React Hooks for State
| Hook | Purpose | Returns |
|---|---|---|
useMeshState(path) | Read and write a state path | [value, setValue] |
useMeshSelector(selector) | Read derived state | value |
useMesh() | Access the mesh instance | mesh |
import { useMeshState, useMeshSelector, useMesh } from "statemesh-core";
function Example() {
const [theme, setTheme] = useMeshState<"light" | "dark">("theme");
const itemCount = useMeshSelector((s) => s.cart.items.length);
const mesh = useMesh();
return (
<div>
<p>Theme: {theme}</p>
<p>Items: {itemCount}</p>
<button onClick={() => mesh.reset()}>Reset</button>
</div>
);
}Important Notes
TIP
setState and setPath trigger synchronous notifications to all subscribers. If you need to make multiple updates and only notify once, use mesh.batch().
WARNING
getState() returns a reference to the current state object. Do not mutate it directly — always use setState(), setPath(), or actions/transactions. Direct mutation bypasses subscriptions and can corrupt undo/redo history.
Next Steps
- Actions — Named mutations with error handling
- Selectors & Computed — Derived state with caching
- Batch Operations — Group multiple updates
