Types
The types of the main API are exported from react-state-custom; Scheduler and ScheduledTask from react-state-custom/schedulers.
StoreState
What useStore returns, and what select and storeRef(params).get() see: every key of State is optional, because it is undefined until the store has run once.
type StoreState<State> = { readonly [K in keyof State]?: State[K] }The keys are read-only: a store changes its state in its own hook, and every reader shares what it published. Writing to the proxy throws in development, get() returns a frozen snapshot, and select receives the store's own data. Only the keys are: an array or object under a key keeps its type, and a read-only key still passes where a mutable type is expected.
StoreRef
Returned by storeRef(params). See storeRef.
type StoreRef<State> = {
readonly name: string // "name?params"
readonly ready: boolean // the running instance has published at least once; false once it is torn down
readonly error: unknown // what the hook threw while the instance is disabled, else undefined
get(): StoreState<State>
subscribe(listener: (state: StoreState<State>, changedKey: keyof State) => void): () => void
retain(): () => void
}get()returns a frozen snapshot, the same object until the state changes, so it can be thegetSnapshotofuseSyncExternalStore. It never subscribes and never starts a store. Before anything runs the instance it returns{}.subscribe()keeps the context alive while subscribed and fires once per changed key. All calls of one store update get the same snapshot, the oneget()returns: the complete new state, all keys of the update applied before the first call. The listener must not throw: an error thrown by any subscriber is rethrown to the store that published the change, and its error boundary disables that store.retain()runs the instance through the globalAutoRootCtxand counts as a reader. Call the returned function to release. Logs a development error if noAutoRootCtxis mounted within a second.
StatesOf
What useMultipleStore(refs) returns: the StoreState of each ref, in order. A tuple of refs gives a tuple, an array gives an array.
type StatesOf<Refs extends readonly StoreRef<any>[]> = { -readonly [K in keyof Refs]: /* StoreState of Refs[K] */ }StoreOptions
The options of createStore.
type StoreOptions = {
timeToClean?: number
schedule?: Scheduler
}StoreReadOptions / StoreSelect
The options of useStore and useMultipleStore.
type StoreReadOptions = { schedule?: Scheduler } // useStore(params, options)
type StoreSelect<S, R> = { // useStore(params, { select, ... })
select: (state: S) => R
isEqual?: (a: R, b: R) => boolean // default: Object.is one level deep
schedule?: Scheduler
}Scheduler / ScheduledTask
What the schedule options take: made by sync(), frame(), throttle(ms), debounce(ms, { maxWait }) and idle(ms), or written by you. See Schedulers.
type Scheduler = { readonly name: string, task(run: () => void): ScheduledTask }
type ScheduledTask = { request(): void, cancel(): void }StoreParams
The argument list of useStore and storeRef: [params?: Readonly<Params>] when Params has no required keys, [params: Readonly<Params>] otherwise. The store hook receives Readonly<Params> too.
Params are read-only because their values name the instance. A reader reads them again only when it gets a different object, so pass a new one (useStore({ id })) rather than changing one you passed: a changed object keeps its reader on the old instance.
Every value of the params must be a primitive (string, number, bigint, boolean, null or undefined), so the identity of an instance is deterministic. The constraint is written over the keys of the params type, so an interface qualifies as well as a type.
Store
What createStore returns: Store<Params, State>, the pair { useStore, storeRef }.
UseStore
The type of a store's useStore, Store<Params, State>['useStore'], for a component or helper that takes a store's hook:
interface UseStore<Params, State> {
<R>(params: Params, options: StoreSelect<StoreState<State>, R>): R // params may be undefined when none is required
(params?: Params, options?: StoreReadOptions): StoreState<State>
}
const Label = ({ useLabel }: { useLabel: UseStore<{ id: string }, { label: string }> }) =>
<b>{useLabel({ id: 'a' }, { select: s => s.label ?? '' })}</b>