Skip to content

State Management

Patterns for local state, derived data, and cross-collection composition in Routier applications.

Overview

State management in Routier involves managing application state through collections, live queries, and derived data. Routier provides built-in features that make state management straightforward and efficient.

Key Concepts

Collections as State

Collections act as your primary state containers:

ts
class AppContext extends DataStore {
  users = this.collection(userSchema).proxy().create();
  products = this.collection(productSchema).proxy().create();
}

Live Queries

Keep UI in sync with data changes automatically:

ts
ctx.users.subscribe().toArray((result) => {
  if (result.ok === "success") {
    console.log("Users:", result.data); // Automatically updates when users change
  }
});

Note: With .subscribe(), you must use callback-based methods (not async methods like toArrayAsync()).

Live queries reach other browser tabs, and other worker threads in Node, because change notifications travel over a BroadcastChannel. A sender cannot see who is listening on the other end of one, so by default every save publishes its changes in case another tab is subscribed.

If the process is the only one reading the database — a server, a script, a single-tab app — set crossTabSync: false on the store. Saves then skip that work whenever nothing in the current process is subscribed, which the repository benchmark measures at roughly 10% of insert time. Subscriptions within the process keep working. See Live Queries.

Change Tracking

All modifications are tracked automatically until saved:

ts
user.name = "New Name"; // Tracked automatically
await ctx.saveChangesAsync(); // Persisted

Derived State

Compute derived data from your collections:

ts
const stats = {
  totalUsers: await ctx.users.countAsync(),
  activeUsers: await ctx.users.where((u) => u.isActive).countAsync(),
};

Patterns

  • Single Source of Truth: Collections serve as your data source
  • Automatic Updates: Live queries keep UI in sync
  • Explicit Persistence: Changes saved with saveChangesAsync()
  • Type Safety: Full TypeScript support

Released under the MIT License.