Events & slices

Name what happened, type its payload, and handle it synchronously in the slices that own the state.

Events describe what happened

An event is an object with a string type. createEvent<P>(name) creates a function that accepts a payload P. Without a payload generic, call the creator without arguments. Creators expose a .type string and a .match(event) boolean check against the event type; match does not validate payload data or act as a TypeScript type predicate.

The optional prepare callback takes one argument and must return an object containing payload. Validate external data before dispatching: event creators do not perform runtime schema validation.

events.ts
import { createEvent } from "@carere/solux";

const renamed = createEvent<string>("project/renamed");
const cleared = createEvent("project/cleared");
const event = renamed("Observatory");
// { type: "project/renamed", payload: "Observatory" }
console.log(renamed.type, renamed.match(event));
cleared();

Slices own their transitions

createSlice({ initialState, handlers }) returns getInitialState() and handler(state, event). The builder’s addHandler binds an event type to a typed handler. Update the supplied state synchronously; returned replacement objects are not used. A second registration for the same event type replaces the earlier handler within that slice.

The slice retains its supplied initial-state object. getInitialState() is not a factory or an isolation boundary. Allocate a new slice with new nested state for each independent store.

project.ts
import { createEvent, createSlice } from "@carere/solux";

const renamed = createEvent<string>("project/renamed");
const project = createSlice({
  initialState: { name: "Untitled" },
  handlers: (builder) => builder.addHandler(renamed, (state, event) => {
    state.name = event.payload;
  }),
});

Compose by state shape

combineSlices({ counter, project }) creates a root slice with the corresponding keys. Each child handler receives its own part of state for every dispatched event, so multiple slices can react to the same event. Child handlers run in the map’s key order. createHandler<S>(builderCallback) is also exported when you need a handler without an initial-state wrapper.

store.ts
import { combineSlices, configureStore } from "@carere/solux";
// counter and project are fresh slices created in this factory.
const store = configureStore({
  rootSlice: combineSlices({ counter, project }),
});
store.dispatch(renamed("Observatory"));
console.log(store.state.project.name);