Skip to main content
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

key
string
A unique identifier for this store instance.
defaultValue
T
The initial value for the store. Can be a primitive or an object.
scope
string
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

FeatureuseStateuseStore
ScopeComponent-localApplication-wide (by key)
APITuple [value, setter]Flattened object with fields + setters
Auto-settersNoYes (per field)
NamespacingNoYes (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)