Patterns
Architectural patterns and best practices for building with Commiq.
Patterns
These pages cover the recurring architectural decisions in a Commiq application. Each one reflects how the library is designed to be used, including where a pattern has a cost or a limit.
Every snippet uses only exported APIs and is written to be copy-pasted.
Two things that apply everywhere
Declare state fields readonly. Every state-reading surface is typed DeepReadonly<S>, so a mutable Item[] field cannot be spread out of ctx.state and written back — { ...ctx.state, other: 1 } is a compile error. One keyword per field makes both forms of setState work everywhere. See store file structure.
Nothing propagates out of queue() or flush(). Neither ever rejects. A failure is observed through the CommandHandle returned by queue(), through StoreOptions.onError, or through the builtin error events — never through a try/catch at the dispatch site. See error handling.
Store File Structure
Organize store files, and why state fields must be declared readonly.
Typed Command Definitions
Use createCommandDef so a command's name and payload type travel together.
Domain Hooks
Encapsulate store interactions in a reusable React hook API.
Async Loading States
Track pending and error state with useCommandStatus instead of state fields.
Event-Driven Side Effects
Trigger notifications, navigation, and analytics from store events.
Error Handling and Recovery
Observe failures through onError, command handles, and builtin error events.
Effects and Cancellation
Concurrency modes, cancellation, and error reporting in the effects plugin.
Real-Time Transports
Bridge WebSockets, Socket.IO, and Server-Sent Events to a store.
Multi-Store Coordination
Route events between independent stores with a refcounted event bus.
Optimistic Updates
Apply state immediately, then confirm or roll back.
State Normalization
Structure collections for lookups, targeted updates, and per-entity selectors.
Testing Stores and Hooks
Test commands, events, failures, hooks, and effects deterministically.
Composing Plugins
Attach devtools, effects, and OpenTelemetry to one store, and dispose them.
Command Validation
Guards for business rules, assertions for developer invariants.
Dependency Injection
Provide typed dependencies to handlers for testability and flexibility.
Deferred Cleanup
Guarantee resource cleanup with ctx.defer, on success and on failure.