Complete documentation for the react-state-custom API.
Note: For most applications, you only need
createStoreandAutoRootCtx. The other APIs are lower-level primitives used internally or for advanced customization.
The main entry point. Converts a standard React hook into a shared, auto-managed store.
function createStore<Params, State>(
name: string,
useFn: (params: Params, preState: Partial<State>) => State,
timeToClean?: number,
AttachedComponent?: React.FC<Params>
): {
useStore(params: Params): State;
useCtxState(params: Params): Context<State>;
}name(string): A unique namespace for this store (e.g.,'user','cart').useFn(function): Your custom hook. Receivesparamsand optionalpreState.timeToClean(number, optional): Time in milliseconds to keep the store alive after the last subscriber unmounts. Defaults to0.AttachedComponent(Component, optional): A React component that renders alongside the store root. Useful for side effects (like data fetching or logging) that should run exactly once per store instance.
useStore: The consumer hook. Call this in your components to read state. It returns a proxy that automatically tracks which properties you access to optimize re-renders.useCtxState: Returns the rawContextobject. Useful for advanced integrations.
const useCounter = ({ initial }) => {
const [count, setCount] = useState(initial);
return { count, setCount };
};
export const { useStore } = createStore('counter', useCounter);The global manager component. Must be mounted once at the top of your application.
function AutoRootCtx(props: {
Wrapper?: React.FC<{ children: React.ReactNode }>;
debugging?: boolean;
}): JSX.ElementWrapper(Component, optional): A wrapper component for each store instance (e.g., an ErrorBoundary). Defaults toReact.Fragment.debugging(boolean, optional): Iftrue, renders a raw view of the state in the DOM for debugging.
function App() {
return (
<>
<AutoRootCtx Wrapper={ErrorBoundary} />
<Routes />
</>
);
}A floating inspector to visualize all active stores and their state in real-time.
function DevToolContainer(props: {
toggleButton?: string;
Component?: DataViewComponent;
style?: React.CSSProperties;
children?: React.ReactNode;
}): JSX.ElementtoggleButton(string, optional): Text for the toggle button.Component(Component, optional): Custom renderer for state values. Defaults to a JSON tree view.children(ReactNode, optional): Custom trigger button content.
import { DevToolContainer } from 'react-state-custom';
import 'react-state-custom/dist/react-state-custom.css';
<DevToolContainer />These APIs are used internally by createStore. You generally don't need them unless you're building custom abstractions.
Creates a headless "Root" component that runs a hook and publishes its result to a context.
function createRootCtx<Params, State>(
name: string,
useFn: (params: Params, preState: Partial<State>) => State
): {
Root: React.FC<Params>;
useCtxState(params: Params): Context<State>;
// ...other internal helpers
}Connects a createRootCtx result to the AutoRootCtx system for automatic mounting.
function createAutoCtx(
rootCtx: ReturnType<typeof createRootCtx>,
timeToClean?: number,
AttachedComponent?: React.FC
): ResultHook to retrieve a Context instance by name.
function useDataContext<T>(name: string): Context<T>Hooks to publish values from a component into a context.
useDataSource(ctx, 'key', value);
useDataSourceMultiple(ctx, ['key1', value1], ['key2', value2]);Hooks to manually subscribe to specific context keys.
const value = useDataSubscribe(ctx, 'key');
const { key1, key2 } = useDataSubscribeMultiple(ctx, 'key1', 'key2');Constraint for store parameters. All params must be primitive values to ensure deterministic IDs.
type ParamsToIdRecord = Record<
string,
string | number | bigint | boolean | null | undefined
>;