Getting Started with Store#

Prerequisites

Before continuing, make sure you're familiar with: SignalX Core basics, Signals, Components

@sigx/store provides centralized, reactive state built on the same signal core that powers your components. You define a store once with defineStore, describe its state, actions, and derived getters inside a setup function, and then call the returned factory anywhere to get a live, reactive instance.

Because the state is signal-backed, reading store.state.x inside a component's render function makes that component re-render automatically when the value changes. There is no boilerplate selector layer and no manual subscription required for rendering.

Why a store?#

  • Centralized state shared across components instead of prop-drilling.
  • Signal-backed reactivity so reads in render functions update automatically.
  • Actions that wrap mutations and expose lifecycle events (onDispatching, onDispatched, onFailure).
  • Per-property mutation events (onMutated{Key}) for reacting to specific state changes.
  • Automatic cleanup when a store instance is created inside a component — it disposes on unmount.

Installation#

Terminal
npm install @sigx/store

See Installation for peer dependencies and project wiring.

Your first store#

Define a store with defineStore(name, setup). The setup function receives a context object that includes defineState and defineActions. Whatever you return becomes the shape of every instance.

TSX
Loading preview...

How it fits together#

  • defineStore(name, setup) returns a factory function. By convention it is assigned to a useXxxStore const, but it is an ordinary function — calling it creates an instance.
  • Inside setup, defineState(obj) returns { state, events, mutate }. Read and write state directly, or use the typed mutate helpers.
  • defineActions(obj) returns your original callable actions plus onDispatching, onDispatched, and onFailure event namespaces.
  • Calling the factory inside a component(...) setup ties the instance to the component lifecycle: it auto-disposes on unmount.

Note: there is no useStore export. useCounterStore above is just the name we gave the factory returned by defineStore.

Reading and mutating state#

state is a reactive, signal-backed object. You can assign properties directly, or use mutate for value/updater ergonomics. Both paths fire the matching onMutated{Key} event.

TypeScript
const { state, mutate, events } = defineState({ count: 0 });

state.count = 5;                  // direct assignment (fires onMutatedCount)
mutate.count(42);                 // set via helper
mutate.count(prev => prev + 1);   // functional update

events.onMutatedCount.subscribe(value => {
    console.log('count is now', value);
});

Next steps#