State
A reactive state management system with subscriptions, computed values, batched updates,
Redux-style actions, local-storage persistence, and selector functions.
Access it via Aura.state.
Quick Start
Initialize default state, subscribe to changes, and update values reactively.
import Aura from 'aurajs'; // Set defaults (merged with any persisted data) Aura.state.init({ count: 0, user: null, theme: 'dark' }); // Subscribe to a key Aura.state.subscribe('count', (newVal, oldVal) => { console.log(`count: ${oldVal} -> ${newVal}`); }); // Update the value Aura.state.set('count', 1); // Logs: "count: 0 -> 1"
init() core
Initialize the state store with default values. If previously persisted data exists in localStorage, it is merged on top of the defaults (persisted values take priority).
| Param | Type | Description |
|---|---|---|
| defaults | Record<string, unknown> | An object of key-value pairs to use as the initial state. |
Aura.state.init({ todos: [], filter: 'all', darkMode: true });
get() core
Retrieve the current value for a given key. If a computed() value is registered under the same name, the computed selector runs instead. Returns undefined if the key does not exist.
| Param | Type | Description |
|---|---|---|
| key | string | The state key to look up. |
const count = Aura.state.get('count'); // number | undefined const user = Aura.state.get<User>('user'); // User | undefined (TS)
set() core
Set a value in the store. If the new value is strictly equal (===) to the current value, the update is skipped. Otherwise, emits state:<key> and state:change events (unless inside a batch()).
| Param | Type | Description |
|---|---|---|
| key | string | The state key to update. |
| value | unknown | The new value to store. |
Aura.state.set('count', 42); Aura.state.set('user', { name: 'Alice', role: 'admin' });
getAll() utility
Return a shallow copy of the entire state object. Useful for debugging or serialization.
This method takes no parameters.
const snapshot = Aura.state.getAll(); console.log(snapshot); // { count: 42, user: {...}, theme: 'dark' }
subscribe() reactive
Listen for changes to a specific state key. The callback receives the new and old values. Returns an unsubscribe function for easy cleanup.
| Param | Type | Description |
|---|---|---|
| key | string | The state key to watch. |
| fn | Function | Callback invoked with (newVal, oldVal) whenever the key changes. |
Returns a () => void unsubscribe function.
const unsub = Aura.state.subscribe('theme', (newVal, oldVal) => { document.body.className = newVal; }); // Later, stop listening unsub();
computed() reactive
Register a derived value that is computed from the full state. When you call get(name), the selector runs against the current state instead of performing a direct lookup.
| Param | Type | Description |
|---|---|---|
| name | string | The virtual key name for this computed value. |
| selector | Selector | A function (state) => derivedValue that computes the value from the full state. |
Aura.state.computed('activeTodos', (state) => { return state.todos.filter(t => !t.done); }); // Now use it like any other key const active = Aura.state.get('activeTodos'); console.log(active.length);
batch() performance
Group multiple set() calls into a single batch. Individual state:<key> events are deferred until the batch function completes, then fired all at once. A single state:batch event is also emitted with all changes.
| Param | Type | Description |
|---|---|---|
| fn | Function | A synchronous function that calls set() one or more times. |
Aura.state.batch(() => { Aura.state.set('loading', false); Aura.state.set('user', userData); Aura.state.set('token', jwt); }); // All three state:<key> events fire here, after the batch // Plus one state:batch event with all changes
action() advanced
Register a named action (reducer-style). Actions receive the full current state and an optional payload, and return a new state object. Changed keys are automatically updated via set().
| Param | Type | Description |
|---|---|---|
| name | string | Unique action name used with dispatch(). |
| handler | Action | Function (state, payload?) => newState. Return the full new state object. |
Aura.state.action('increment', (state, amount) => ({ ...state, count: state.count + (amount ?? 1) })); Aura.state.action('addTodo', (state, text) => ({ ...state, todos: [...state.todos, { text, done: false }] }));
dispatch() advanced
Execute a registered action by name. Also supports a built-in 'fetch' action that fetches JSON from a URL and stores it under a key. Throws if the action name is not found.
| Param | Type | Description |
|---|---|---|
| actionName | string | Name of a registered action, or the built-in 'fetch'. |
| payload | unknown | Data passed to the action handler. For 'fetch', pass { url, key }. |
// Dispatch a custom action await Aura.state.dispatch('increment', 5); console.log(Aura.state.get('count')); // previous + 5 // Built-in fetch action await Aura.state.dispatch('fetch', { url: '/api/users', key: 'users' }); // Aura.state.get('users') now has the fetched JSON
select() utility
Run an ad-hoc selector function against the current state and return the result. Unlike computed(), this does not register anything -- it is a one-shot query.
| Param | Type | Description |
|---|---|---|
| selector | Selector<T> | A function that receives the full state and returns a derived value. |
const total = Aura.state.select(s => s.todos.length); const admin = Aura.state.select(s => s.user?.role === 'admin');
persist() utility
Save the entire current state to localStorage under the key app_state. On the next init() call, persisted data is automatically restored and merged with defaults.
This method takes no parameters.
// Save state before the user leaves window.addEventListener('beforeunload', () => { Aura.state.persist(); });
reset() destructive
Clear all state and optionally replace it with new defaults. Emits state:<key> for every key whose value changed, plus a state:reset event with the new state.
| Param | Type | Description |
|---|---|---|
| defaults | Record<string, unknown> | Optional new state. If omitted, state is set to an empty object {}. |
// Reset to empty Aura.state.reset(); // Reset with new defaults Aura.state.reset({ count: 0, theme: 'light' });
Emitted Events
The state module emits events via the Aura event bus. Subscribe with Aura.on() or Aura.state.subscribe().
| Event | Payload | Description |
|---|---|---|
| state:<key> | newVal, oldVal | Fired when a specific key changes via set(). |
| state:change | key, newVal, oldVal | Fired on every individual key change (outside of batch). |
| state:batch | [key, val, old][] | Fired after a batch() completes with all changes. |
| state:reset | newState | Fired when reset() is called. |
// Listen to all state changes Aura.on('state:change', (key, newVal, oldVal) => { console.log(`${key} changed`, oldVal, '->', newVal); }); // Listen to batch completions Aura.on('state:batch', (changes) => { console.log(`${changes.length} keys updated in batch`); });