Write once. Stash anywhere.
The simplest way to manage React state — a tiny, fully-typed, zero-dependency
store. One createStore, no providers, no reducers.
npm install unistashimport { createStore } from "unistash";
const useCounter = createStore({
state: { count: 0 },
actions: {
increment: (s) => ({ count: s.count + 1 }),
add: (s, n: number) => ({ count: s.count + n }),
},
computed: {
doubled: (s) => s.count * 2,
},
});
function Counter() {
const { count, doubled, increment } = useCounter();
return (
<button onClick={increment}>
{count} ({doubled})
</button>
);
}State, computed values, and actions all come from one hook.
// re-renders only when count changes
const count = useCounter((s) => s.count);
import { shallow } from "unistash";
const slice = useCounter((s) => ({ a: s.count, b: s.doubled }), shallow);useCounter.getState();
useCounter.setState({ count: 5 });
const unsubscribe = useCounter.subscribe((snapshot) => {});- Zero dependencies — just React (a peer).
- Fully typed — autocomplete on state, computed, and actions.
- Selectors — fine-grained re-renders, opt-in.
- SSR-ready — built on
useSyncExternalStore, no hydration mismatch. - No boilerplate — no providers, no reducers.
pnpm install
pnpm build
pnpm testMIT