API Reference
Legend:
?means optional
initStore
Create a standalone store instance without React.
import { initStore } from "floppy-disk";
const store = initStore(initialState, options);Parameters
initialState: The initial state of the store, must be an objectoptions?onFirstSubscribe?: Called when the first subscriber is addedonSubscribe?: Called every time a subscriber is addedonUnsubscribe?: Called every time a subscriber is removedonLastUnsubscribe?: Called when the last subscriber is removedonStateChange?: Called whenever state changes (does not register as a subscriber)allowSetStateServerSide?: AllowsetStateon server (disabled by default)
Return Value
store: Store Instancestore.getState(): Get the current statestore.setState(value): Update the state (accepts partial object or updater function)store.subscribe(fn): Subscribe to state changes (returns unsubscribe function)store.getSubscriberCount(): Get the number of subscribers
createStore
Creates a store with built-in React bindings.
import { createStore } from "floppy-disk/react";
const useStore = createStore(initialState, options);Parameters
initialState: The initial state of the store, must be an objectoptions?onFirstSubscribe?: Called when the first subscriber is addedonSubscribe?: Called every time a subscriber is addedonUnsubscribe?: Called every time a subscriber is removedonLastUnsubscribe?: Called when the last subscriber is removedonStateChange?: Called whenever state changes (does not register as a subscriber)allowSetStateServerSide?: AllowsetStateon server (disabled by default)
Return Value
-
useStore()- Parameters (optional)
initialState?: Initial state applied once on first render (also updates the store)
- Return Value
state: Proxied state with automatic tracking (component re-renders only when accessed values change)
- Parameters (optional)
-
useStoremethodsuseStore.getState(): Get the current stateuseStore.setState(value): Update the state (accepts partial object or updater function)useStore.subscribe(fn): Subscribe to state changes (returns unsubscribe function)useStore.getSubscriberCount(): Get the number of subscribers
createStores
Creates a factory for multiple stores identified by a key.
import { createStores } from "floppy-disk/react";
const getStore = createStores(initialState, options);
const useStore = getStore(key);Parameters
initialState: The initial state for each store instance, must be an objectoptions?onFirstSubscribe?: Called when the first subscriber is addedonSubscribe?: Called every time a subscriber is addedonUnsubscribe?: Called every time a subscriber is removedonLastUnsubscribe?: Called when the last subscriber is removedonStateChange?: Called whenever state changes (does not register as a subscriber)allowSetStateServerSide?: AllowsetStateon server (disabled by default)
Return Value
-
getStore(key?)- Parameters
key?: Unique identifier for the store instance (object, will be hashed)
- Return Value
useStore: A store bound to the given key (lazily created and cached)
- Parameters
-
useStore()- Parameters (optional)
initialState?: Initial state applied once per store instance (also updates the store once)
- Return Value
state: Proxied state with automatic tracking (component re-renders only when accessed values change)
- Parameters (optional)
-
useStoremethodsuseStore.getState(): Get the current stateuseStore.setState(value): Update the state (accepts partial object or updater function)useStore.subscribe(fn): Subscribe to state changes (returns unsubscribe function)useStore.getSubscriberCount(): Get the number of subscribersuseStore.delete(): Delete the store instance (only works when no active subscribers)
-
useStorepropertiesuseStore.key: The original key objectuseStore.keyHash: Deterministic hash of the key
Notes
- Each unique key creates an isolated store
- Stores are lazily created and cached
.delete()will reset state and remove the store from cache- Cannot delete a store while it still has active subscribers
createQuery
Creates a query factory for managing async state with caching and lifecycle.
import { createQuery } from "floppy-disk/react";
const getQuery = createQuery(queryFn, options);
const useQuery = getQuery(variable);Parameters
queryFn: Async function that returns data- Receives
(variable, currentState, variableHash)
- Receives
options?staleTime?: Time (ms) data is considered fresh (default: 2500)gcTime?: Time (ms) before unused queries are garbage collected (default: 5 minutes)revalidateOnFocus?: Revalidate on window focus (default: true)revalidateOnReconnect?: Revalidate on network reconnect (default: true)onSuccess?: Called when query succeedsonError?: Called when query fails and no more retriesonSettled?: Called after success or final failureshouldRetry?: Control retry behavior (default: retry once with 1500ms delay)onFirstSubscribe?: Called when the first subscriber is addedonSubscribe?: Called every time a subscriber is addedonUnsubscribe?: Called every time a subscriber is removedonLastUnsubscribe?: Called when the last subscriber is removedonStateChange?: Called whenever state changes (does not register as a subscriber)allowSetStateServerSide?: AllowsetStateon server (disabled by default)
Return Value
-
getQuery(variable?)- Parameters
variable?: Query parameter (object, used as key)
- Return Value
useQuery: Query instance (lazily created and cached per variable)
- Parameters
-
useQuery()- Parameters (optional)
initialData?: Initial data (applied once per query instance)initialDataIsStale?: Treat initial data as stale (default: false)revalidateOnMount?: Auto revalidate on mount (default: true)keepPreviousData?: Keep previous data during variable change
- Return Value
state: Proxied query state with automatic tracking
- Parameters (optional)
-
useQuerymethodsuseQuery.execute(options?): Execute query- execute always runs if there is no ongoing execution
- If there is an ongoing execution:
overwriteOngoingExecution: true(default) → starts a new execution & ignores the previous oneoverwriteOngoingExecution: false→ reuses the existing promise (deduped)
useQuery.revalidate(options?): Execute only if stale or invalidateduseQuery.invalidate(options?): Mark as invalid (and execute if active)useQuery.reset(): Reset to initial stateuseQuery.delete(): Delete query (only if no subscribers)useQuery.optimisticUpdate(data): Apply optimistic datauseQuery.rollbackOptimisticUpdate(): Restore previous datauseQuery.getState(): Get current state-
useQuery.setState(value): Manually update state (not recommended) useQuery.subscribe(fn): Subscribe to state changesuseQuery.getSubscriberCount(): Get the number of subscribers
-
getQuerymethodsgetQuery.executeAll(): Execute all queriesgetQuery.revalidateAll(): Revalidate all stale or invalidatedgetQuery.invalidateAll(): Invalidate allgetQuery.resetAll(): Reset all queries
Notes
- Queries are keyed by query variable (deterministic hash)
- Each variable has its own isolated state
- Invalidated queries bypass
staleTime - Unused queries are garbage collected after gcTime
createMutation
Creates a mutation store for handling async operations that modify data.
import { createMutation } from "floppy-disk/react";
const useMutation = createMutation(mutationFn, options);Parameters
mutationFn: Async function that performs the mutation- Receives
(variable, stateBeforeExecute)
- Receives
options?onSuccess?: Called when mutation succeedsonError?: Called when mutation failsonSettled?: Called after success or erroronFirstSubscribe?: Called when the first subscriber is addedonSubscribe?: Called every time a subscriber is addedonUnsubscribe?: Called every time a subscriber is removedonLastUnsubscribe?: Called when the last subscriber is removedonStateChange?: Called whenever state changes (does not register as a subscriber)allowSetStateServerSide?: AllowsetStateon server (disabled by default)
Return Value
-
useMutation()- Return Value
state: Proxied mutation state with automatic tracking
- Return Value
-
useMutationmethodsuseMutation.execute(variable?): Execute mutationuseMutation.reset(): Reset state to initialuseMutation.getState(): Get current state-
useMutation.setState(value): Manually update state (not recommended) useMutation.subscribe(fn): Subscribe to state changesuseMutation.getSubscriberCount(): Get the number of subscribers
Notes
- No retry mechanism
- Promise never rejects (always resolves with
{ variable: TVariable; data?: TData; error?: TError }) - If execution triggered while there is inprogress execution:
- Only the latest execution updates state
- Previous executions are ignored
useMutation
A hook for managing mutation state without a global store.
import { useMutation } from "floppy-disk/react";
const [state, actions] = useMutation(mutationFn, options);Parameters
mutationFn: Async function that performs the mutation- Receives (variable, stateBeforeExecute)
- Does not need to be memoized
options?onSuccess?: Called when mutation succeedsonError?: Called when mutation failsonSettled?: Called after success or error
Return Value
[state, actions]state: Current mutation state (render snapshot)actions.execute(variable?): Execute mutationactions.reset(): Reset state to initialactions.getLatestState(): Get latest state (not tied to render)
Notes
- Local-only (not shared across components)
- No retry mechanism
- Promise never rejects (always resolves with
{ variable: TVariable; data?: TData; error?: TError }) - If execution triggered while there is inprogress execution:
- Only the latest execution updates state
- Previous executions are ignoredOnly latest execution updates state
- Safe against stale closures (always uses latest function & callbacks)