Quick Start
From zero to productive in 2 minutes
Install it
npm install zenboxYour first store
Let's build a simple counter. Here's the entire thing:
import { createStore, useStore } from "zenbox";
// Create the store - types are inferred automatically
const counter = createStore({
count: 0,
increment: () =>
counter.setState((s) => {
s.count++;
}),
decrement: () =>
counter.setState((s) => {
s.count--;
}),
reset: () => counter.setState({ count: 0 }),
});
// Use it in a component
function Counter() {
const { count, increment, decrement, reset } = useStore(counter);
return (
<div>
<h2>Count: {count}</h2>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
</div>
);
}That's it. No interfaces, no providers, no setup. It just works.
Add some Vue magic
Now let's add computed values and watchers:
import { useComputed, useWatch } from "zenbox";
function EnhancedCounter() {
// Computed values - update automatically when dependencies change
const doubled = useComputed(() => counter.value.count * 2);
const isEven = useComputed(() => counter.value.count % 2 === 0);
// Watch for changes
useWatch(
() => counter.value.count,
(newCount, oldCount) => {
if (newCount > 10) {
console.log("Getting high!");
}
}
);
return (
<div>
<p>Doubled: {doubled}</p>
<p>Is even: {isEven ? "Yes" : "No"}</p>
<button onClick={counter.value.increment}>Increment</button>
</div>
);
}Multiple stores? No problem
const user = createStore({
name: "Alice",
email: "alice@example.com",
});
const posts = createStore({
items: [],
addPost: (title) =>
posts.setState((s) => {
s.items.push({ id: Date.now(), title, author: user.value.name });
}),
});
function Summary() {
// Compute across stores - ZenBox tracks dependencies automatically
const userSummary = useComputed(
() => `${user.value.name} has written ${posts.value.items.length} posts`
);
return <p>Summary: {userSummary}</p>;
}Optimize re-renders with selectors
When your component only depends on specific fields from the store, use selectors to prevent unnecessary re-renders.
// ❌ Re-renders on any store change, even if age changes
const { name, email, age } = useStore(userStore);
// ✅ Only re-renders when name or email changes
const { name, email } = useStore(userStore, { pick: ["name", "email"] });For convenience, use usePick as a shortcut for selecting specific fields:
// Same as above, but more concise
const { name, email } = usePick(userStore, "name", "email");That's really it
You now know everything you need to be productive with ZenBox:
createStore()for your stateuseStore()to subscribe to state changesusePick()to optimize re-rendersuseComputed()for derived valuesuseWatch()to react to changes
The rest is just building your app. Check out the other guides for advanced patterns.