@molecule/app-state-zustand
Provider bond · state · App (browser) · v1.0.2 · Apache-2.0
Zustand state provider for molecule.dev
npm install @molecule/app-state-zustandnpm · Source on GitHub · Implements @molecule/app-state
How it works
@molecule/app-state-zustand is a provider bond on the app (browser) side: it implements the state core interface (@molecule/app-state) with a concrete vendor or library behind it.
Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.
import { setProvider } from '@molecule/app-state'
import { createStore, provider } from '@molecule/app-state-zustand'
setProvider(provider)
// persist is a zustand-bond EXTENSION: the core createStore() accepts only the
// portable StoreConfig — create persisted stores via the bond's own createStore.
const store = createStore({
initialState: { theme: 'light', draft: '' },
persist: { name: 'app-settings', partialize: (s) => ({ theme: s.theme }) },
})Works with: @molecule/app-state
Reference
Zustand state provider for molecule.dev.
Implements the StateProvider interface from @molecule/app-state on
zustand/vanilla (with subscribeWithSelector), with optional per-store
persistence and slice helpers for direct-Zustand usage.
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import { setProvider } from '@molecule/app-state'
import { createStore, provider } from '@molecule/app-state-zustand'
setProvider(provider)
// persist is a zustand-bond EXTENSION: the core createStore() accepts only the
// portable StoreConfig — create persisted stores via the bond's own createStore.
const store = createStore({
initialState: { theme: 'light', draft: '' },
persist: { name: 'app-settings', partialize: (s) => ({ theme: s.theme }) },
})
Type
provider
Installation
npm install @molecule/app-state-zustand @molecule/app-state zustand
API
Interfaces
ZustandStoreConfig
Extended store config for Zustand-specific options.
interface ZustandStoreConfig<T> extends StoreConfig<T> {
/**
* Enable devtools integration.
*/
devtools?: boolean
/**
* Persist options.
*/
persist?: {
/**
* Storage key.
*/
name: string
/**
* Storage to use (defaults to localStorage).
*/
storage?: Storage
/**
* Partialize the state to persist.
*/
partialize?: (state: T) => Partial<T>
}
}
StoreWithActionsConfig
Store with actions configuration.
interface StoreWithActionsConfig<T extends object, A extends object> {
initialState: T
actions: (set: SetState<T>, get: GetState<T>) => A
name?: string
middleware?: StoreMiddleware<T>[]
devtools?: boolean
persist?: ZustandStoreConfig<T>['persist']
}
SliceConfig
Configuration for a Zustand store slice (name, initial state, and action creators).
interface SliceConfig<T extends object, A extends object> {
name: string
initialState: T
actions: (set: SetState<T>, get: GetState<T>) => A
}
Slice
A Zustand store slice: a named partition of state with its initial values and action creators.
interface Slice<T extends object, A extends object> {
name: string
initialState: T
actions: (set: SetState<T>, get: GetState<T>) => A
}
StoreConfig
Configuration for creating a store (initial state, optional name, and middleware chain).
interface StoreConfig<T> {
/**
* Initial state value.
*/
initialState: T
/**
* Optional name for debugging.
*/
name?: string
/**
* Optional middleware functions.
*/
middleware?: StoreMiddleware<T>[]
}
Store
Reactive state container with getState, setState, subscribe, and destroy.
All state management providers must implement this interface.
interface Store<T> {
/**
* Gets the current state.
*/
getState(): T
/**
* Sets the state (partial or via updater function).
*/
setState(partial: Partial<T> | ((state: T) => Partial<T>)): void
/**
* Subscribes to state changes.
* Returns an unsubscribe function.
*/
subscribe(listener: StateListener<T>): () => void
/**
* Destroys the store and cleans up subscriptions.
*/
destroy(): void
}
StateProvider
State provider interface that all state management bond packages must implement. Provides the store creation factory.
interface StateProvider {
/**
* Creates a new store.
*/
createStore<T>(config: StoreConfig<T>): Store<T>
}
Types
StoreMiddleware
Store middleware function. Wraps the set function to intercept
state updates (e.g. for logging, persistence, or devtools).
type StoreMiddleware<T> = (set: SetState<T>, get: GetState<T>) => SetState<T>
set— The original setState function to wrap.get— A function returning the current state.
SetState
Function to update store state with a partial object or updater function.
type SetState<T> = (partial: Partial<T> | ((state: T) => Partial<T>)) => void
GetState
Get state function type.
type GetState<T> = () => T
StateListener
Callback invoked whenever store state changes.
type StateListener<T> = (state: T, prevState: T) => void
state— The new state after the update.prevState— The state before the update.
Functions
createProvider()
Creates a Zustand state provider for use with setProvider() from @molecule/app-state.
function createProvider(): StateProvider
Returns: A StateProvider that creates Zustand-backed stores.
createStoreWithActions(config)
Creates a store with actions (Zustand pattern).
function createStoreWithActions(config: StoreWithActionsConfig<T, A>): Store<T> & A
config— Configuration withinitialStateand anactionsfactory(set, get) => actionMap.
Returns: A molecule Store merged with the action functions, so actions can be called directly on the store.
createSlice(config)
Creates a named slice of state for use with combineSlices. A slice defines a name,
initialState, and an actions factory that receives scoped set/get functions.
function createSlice(config: SliceConfig<T, A>): Slice<T, A>
config— Slice configuration withname,initialState, andactionsfactory.
Returns: A Slice object (the config itself, used as a descriptor by combineSlices).
combineSlices(slices)
Combines multiple slices into a single Zustand store. Each slice's state is nested under
its name key, and each slice's actions are exposed as top-level methods on the store.
function combineSlices(slices: S): Store<Record<string, unknown>>
slices— Array of slices created bycreateSlice.
Returns: A molecule Store with combined state and all slice actions merged onto it.
createStore(config)
Creates a Zustand-backed store that conforms to the molecule Store interface.
Uses zustand/vanilla with subscribeWithSelector middleware. Supports molecule middleware,
and optional persistence to localStorage (or a custom storage backend).
function createStore(config: ZustandStoreConfig<T>): Store<T>
config— Store configuration includinginitialState, optional moleculemiddleware, and optionalpersistconfig withname,storage, andpartialize.
Returns: A molecule Store with getState, setState, subscribe, and destroy.
createSelector(selector, equalityFn)
Creates a memoized selector that only recomputes when the selected value changes
(determined by the equality function, defaulting to Object.is).
function createSelector(
selector: (state: T) => R,
equalityFn?: (a: R, b: R) => boolean,
): (state: T) => R
selector— Function that extracts a derived value from state.equalityFn— Equality comparator for the derived value; defaults toObject.is.
Returns: A memoized selector function that returns the cached result when the derived value is equal.
Constants
provider
Default Zustand state provider instance.
const provider: StateProvider
Core Interface
Implements @molecule/app-state interface.
Bond Wiring
Setup function to register this provider with the core interface:
import { setProvider } from '@molecule/app-state'
import { provider } from '@molecule/app-state-zustand'
export function setupStateZustand(): void {
setProvider(provider)
}
Injection Notes
Requirements
Peer dependencies:
@molecule/app-state^1.0.1
Runtime Dependencies
-
@molecule/app-state -
zustand -
Persistence is best-effort and silent.
persistdefaults to rawlocalStorage(no-ops server-side); read/write failures (quota, private browsing, serialization) are swallowed by design — the in-memory store keeps working, but nothing sticks. Passpersist.storageto use another backend andpartializeto bound what is written. -
Persisted state is shallow-merged over
initialStateon creation — old keys survive shape changes; version/namespace thepersist.namewhen the shape breaks. -
destroy()is a no-op (Zustand v5 has no store destroy) — drop references and call the unsubscribe functions returned bysubscribe(). -
setStateshallow-merges partials/updater results (moleculeStoresemantics). -
createStoreWithActions/createSlice/combineSlicesare direct-Zustand helpers — stores built with them bypass the moleculeStorecontract.