← All @molecule/* packages · App templates
@molecule/app-stateCore interface · state · App (browser) · v1.0.1 · Apache-2.0
Global state management with stores
npm install @molecule/app-state@molecule/app-state is the state core interface on the app (browser) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 3 providers: @molecule/app-state-jotai, @molecule/app-state-redux, @molecule/app-state-zustand.
import { createStore } from '@molecule/app-state'
import { useStore } from '@molecule/app-react'
const uiStore = createStore({ initialState: { sidebarOpen: false } })
function Sidebar() {
const { sidebarOpen } = useStore(uiStore) // subscribes to the store
const toggle = () => uiStore.setState({ sidebarOpen: !sidebarOpen })
}Providers (3): @molecule/app-state-jotai, @molecule/app-state-redux, @molecule/app-state-zustand
Works with: @molecule/app-bond, @molecule/app-logger
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.
Client state management interface for molecule.dev.
Provides a unified state management API that works across different state management solutions (hooks, Zustand, Redux, Jotai, etc.).
import { createStore } from '@molecule/app-state'
import { useStore } from '@molecule/app-react'
const uiStore = createStore({ initialState: { sidebarOpen: false } })
function Sidebar() {
const { sidebarOpen } = useStore(uiStore) // subscribes to the store
const toggle = () => uiStore.setState({ sidebarOpen: !sidebarOpen })
}
core
npm install @molecule/app-state @molecule/app-bond @molecule/app-logger
AsyncStateAsync state tuple.
interface AsyncState<T> {
/**
* Current data value.
*/
data: T
/**
* Whether the state is loading.
*/
loading: boolean
/**
* Error if any occurred.
*/
error: Error | null
}
AsyncStateActionsAsync state actions.
interface AsyncStateActions<T> {
/**
* Sets the data value.
*/
setData(data: T): void
/**
* Sets the loading state.
*/
setLoading(loading: boolean): void
/**
* Sets an error.
*/
setError(error: Error | null): void
/**
* Resets to initial state.
*/
reset(): void
/**
* Executes an async operation, handling loading/error states.
*/
execute<R>(fn: () => Promise<R>): Promise<R>
}
PersistStorageSimple storage adapter interface for persist middleware.
Compatible with localStorage, sessionStorage, and
@molecule/app-storage providers.
interface PersistStorage {
getItem(key: string): string | null
setItem(key: string, value: string): void
}
StateProviderState 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>
}
StoreReactive 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
}
StoreConfigConfiguration 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>[]
}
EqualityFnEquality comparator for selectors. When provided, prevents re-renders if the selected value is equal to the previous one.
type EqualityFn<T> = (a: T, b: T) => boolean
GetStateGet state function type.
type GetState<T> = () => T
SelectorSelector function that derives a value from store state.
type Selector<T, S> = (state: T) => S
SetStateFunction to update store state with a partial object or updater function.
type SetState<T> = (partial: Partial<T> | ((state: T) => Partial<T>)) => void
StateListenerCallback invoked whenever store state changes.
type StateListener<T> = (state: T, prevState: T) => void
StoreMiddlewareStore 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>
combineStores(stores)Combines multiple stores into a single composite store. Each key
in stores becomes a top-level key in the combined state.
function combineStores(stores: { [K in keyof T]: Store<T[K]> }): Store<T>
stores — A record mapping keys to individual stores.Returns: A composite Store that delegates to the individual stores.
createAsyncState(initialData)Creates an async state container with loading/error tracking.
function createAsyncState(initialData: T): [AsyncState<T>, AsyncStateActions<T>]
initialData — The initial data value.Returns: A tuple of [state, actions] for reading and updating the async state.
createSimpleStateProvider()Creates a vanilla JavaScript state provider that manages stores with simple object spreading and listener-based subscriptions.
function createSimpleStateProvider(): StateProvider
Returns: A StateProvider implementation.
createStore(config)Creates a new reactive state store using the bonded provider.
function createStore(config: StoreConfig<T>): Store<T>
config — Store configuration including initial state, actions, selectors, and middleware.Returns: A reactive store instance with getState(), setState(), and subscribe() methods.
getProvider()Retrieves the bonded state provider, throwing if none is configured.
function getProvider(): StateProvider
Returns: The bonded state provider.
hasProvider()Checks whether a state provider is currently bonded.
function hasProvider(): boolean
Returns: true if a state provider is bonded.
loggerMiddleware(name)Logging middleware — logs previous and next state on every update.
function loggerMiddleware(name?: string): StoreMiddleware<T>
name — Optional store name for log prefix (defaults to 'store').Returns: A store middleware that logs state transitions.
persistMiddleware(key, storage)Persist middleware — saves state to storage on every update and restores it on initialization.
Accepts any object implementing PersistStorage (getItem + setItem).
Defaults to in-memory storage.
function persistMiddleware(key: string, storage?: PersistStorage): StoreMiddleware<T>
key — The storage key to persist state under.storage — A PersistStorage-compatible object (defaults to in-memory).Returns: A store middleware that persists state to the given storage.
produce(state, recipe)Simplified produce helper for immutable state updates. Creates a shallow copy, applies the recipe, and returns the result.
function produce(state: T, recipe: (draft: T) => void): T
state — The current state object.recipe — A function that mutates the draft copy.Returns: A new state object with the recipe's mutations applied.
setProvider(provider)Registers a state provider as the active singleton. Called by bond packages during application startup.
function setProvider(provider: StateProvider): void
provider — The state provider implementation to bond.shallowEqual(a, b)Performs a shallow equality comparison between two values.
Returns true if both values have the same top-level keys
with identical values (using Object.is).
function shallowEqual(a: T, b: T): boolean
a — First value to compare.b — Second value to compare.Returns: true if the values are shallowly equal.
simpleProviderPre-created default state provider instance.
const simpleProvider: StateProvider
| Provider | Package |
|---|---|
| Jotai | @molecule/app-state-jotai |
| Redux | @molecule/app-state-redux |
| Zustand | @molecule/app-state-zustand |
Peer dependencies:
@molecule/app-bond ^1.0.1@molecule/app-logger ^1.0.1@molecule/app-bond@molecule/app-loggerDefine stores with {@link createStore} and read them through the framework hook
(useStore(store) in React / the Vue composable) — do NOT import zustand / redux /
jotai directly in a component; that couples you to one library and breaks the swap. For a
large store, pass a selector via the hook's options so a component re-renders only when the
slice it reads changes.
@molecule/app-http) and keep the store for UI/session state.@molecule/app-storage). Persist only non-sensitive UI state, via the storage
ABSTRACTION, never raw localStorage.