The useStore function provides a powerful state management solution with automatic setter generation for object properties. It’s similar to Zustand-style stores, offering a flattened API with individual field setters.
declare function useStore<T>(
key: string,
defaultValue: T,
scope?: string
): Store<StoreShape<T>>;
Parameters
A unique identifier for this store instance.
The initial value for the store. Can be a primitive or an object.
Optional scope to namespace the store key (e.g., “user”, “settings”).
Returns
Returns a Store<T> object with:
- All fields from the default value (flattened)
- Auto-generated setters for each field (e.g.,
setName, setAge)
- A
set() method to replace the entire store value
- Metadata:
key, scope, fullKey
Usage
Basic object store
const body = () => {
const user = useStore('user', {
name: 'John',
age: 30,
email: '[email protected]'
})
return VStack([
Text(`Name: ${user.name}`),
Text(`Age: ${user.age}`),
Button('Increment Age', () => user.setAge(user.age + 1)),
Button('Update Name', () => user.setName('Jane'))
])
}
Functional updates
const body = () => {
const counter = useStore('counter', { count: 0 })
return VStack([
Text(`Count: ${counter.count}`),
Button('Increment', () => {
// Functional update based on previous value
counter.setCount(prev => prev + 1)
})
])
}
Scoped stores
const body = () => {
// Scoped to "settings" namespace
const theme = useStore('theme', {
mode: 'light',
fontSize: 16
}, 'settings')
// Full key will be "settings:theme"
console.log(theme.fullKey) // "settings:theme"
return VStack([
Text(`Mode: ${theme.mode}`),
Button('Toggle Theme', () => {
theme.setMode(theme.mode === 'light' ? 'dark' : 'light')
})
])
}
Replace entire store
const body = () => {
const profile = useStore('profile', {
name: 'John',
bio: 'Developer'
})
return VStack([
Button('Reset Profile', () => {
// Replace entire store object
profile.set({
name: 'Anonymous',
bio: 'No bio'
})
}),
Button('Update with function', () => {
// Functional update of entire store
profile.set(prev => ({
...prev,
name: prev.name.toUpperCase()
}))
})
])
}
Complex nested state
const body = () => {
const app = useStore('app', {
user: { name: 'John', role: 'admin' },
settings: { notifications: true },
count: 0
})
return VStack([
Text(`User: ${app.user.name}`),
Button('Update User', () => {
// Update nested object
app.setUser({
...app.user,
name: 'Jane'
})
}),
Button('Toggle Notifications', () => {
app.setSettings({
...app.settings,
notifications: !app.settings.notifications
})
})
])
}
Auto-generated Setters
For each field in your default value, useStore automatically creates a setter:
const store = useStore('example', {
name: 'John',
age: 30,
isActive: true
})
// Auto-generated setters:
store.setName('Jane')
store.setAge(31)
store.setIsActive(false)
// All setters support functional updates:
store.setAge(prev => prev + 1)
Comparison with useState
| Feature | useState | useStore |
|---|
| Scope | Component-local | Application-wide (by key) |
| API | Tuple [value, setter] | Flattened object with fields + setters |
| Auto-setters | No | Yes (per field) |
| Namespacing | No | Yes (via scope) |
Notes
- Store state persists across component re-renders and is shared by key
- Updates trigger re-renders automatically
- The
scope parameter helps organize stores into namespaces
- All field setters support both direct values and functional updates
- The store object includes metadata (
key, scope, fullKey)