storion
v0.20.1
Published
Reactive stores for modern apps. Type-safe. Auto-tracked. Effortlessly composable
Maintainers
Readme
import { create } from "storion/react";
const [_, useCounter] = create({
state: { count: 0 },
setup: ({ state }) => ({
inc: () => state.count++,
dec: () => state.count--,
}),
});
function Counter() {
const { count, inc } = useCounter((s, a) => ({ count: s.count, ...a }));
return <button onClick={inc}>{count}</button>;
}No Provider. No boilerplate. It just works.
Features
| Feature | Description | | -------------------- | -------------------------------------------- | | 🎯 Auto-tracking | Read state → subscribed automatically | | ⚡ Fine-grained | Only changed state triggers re-renders | | 🔒 Type-safe | Full TypeScript inference, zero manual types | | 🌊 Async-first | Loading states, error handling, Suspense | | 🛠️ DevTools | Time-travel debugging built-in | | 📦 ~4KB | Tiny bundle, no compromises |
Install
npm install storionUsage
Single Store
For isolated features, widgets, or prototypes:
import { create } from "storion/react";
const [_, useAuth] = create({
state: { user: null },
setup: ({ state }) => ({
login: (user) => {
state.user = user;
},
logout: () => {
state.user = null;
},
}),
});Multiple Stores
For apps with shared state (auth, cart, users):
import { store, container, StoreProvider, useStore } from "storion/react";
const authStore = store({
name: "auth",
state: { user: null },
setup: ({ state }) => ({
login: (user) => {
state.user = user;
},
logout: () => {
state.user = null;
},
}),
});
const cartStore = store({
name: "cart",
state: { items: [] },
setup: ({ state, get }) => {
const [auth] = get(authStore); // Cross-store access
return {
add: (item) => {
state.items = [...state.items, item];
},
clear: () => {
state.items = [];
},
};
},
});
const app = container();
function App() {
return (
<StoreProvider container={app}>
<Shop />
</StoreProvider>
);
}
function Shop() {
const { items, add } = useStore(({ get }) => {
const [state, actions] = get(cartStore);
return { items: state.items, add: actions.add };
});
// ...
}Async Data
import { store } from "storion/react";
import { async } from "storion/async";
const usersStore = store({
name: "users",
state: { users: async.fresh([]) },
setup: ({ focus }) => {
const query = async(focus("users"), async (ctx) => {
const res = await fetch("/api/users", { signal: ctx.signal });
return res.json();
});
return { fetch: query.dispatch, refresh: query.refresh };
},
});When to Use What
| Scenario | Use |
| --------------------- | --------------------------- |
| Single feature/widget | create() |
| Multiple stores | store() + container() |
| Testing with mocks | container() + app.set() |
| Persistence | app.use(persist()) |
Documentation
📚 Full Docs — Get Started · Core Concepts · Async · API · Demos
License
MIT © linq2js
