Small state guide
@ilokesto/store works best when the state has a small, clear owner. Think cart contents, a selected workspace, a local command palette model, or a connection status object.
Start with the state boundary
type ConnectionState = {
status: "idle" | "connecting" | "open" | "closed";
lastError: string | null;
};
export const connectionStore = new Store<ConnectionState>({
status: "idle",
lastError: null,
});Keep unrelated concerns in separate stores. A store that contains everything tends to need selectors, reducers, and normalization that this package intentionally does not provide.
Export actions, not random writes
export function markConnecting(): void {
connectionStore.setState((prev) => ({ ...prev, status: "connecting", lastError: null }));
}
export function markClosed(error: string | null): void {
connectionStore.setState({ status: "closed", lastError: error });
}Action functions make replacement semantics obvious and keep callers from forgetting fields.
Read at the edge
Read with getState() where you need a snapshot: a logger, a command handler, or a framework adapter. Subscribe where you need to keep something synchronized over time.
Practical checklist
- Can you describe the state in one type?
- Can updates replace the whole value without hidden deep merge behavior?
- Do subscribers have a clear owner and cleanup path?
- Would middleware be simple enough to run synchronously?
If the answer is no, use a larger state system or build a domain-specific layer around Store<T>.