Skip to content

Reactions & Watch

Derive state from state, and run side-effects outside React.

Reactions — build state from other state

Section titled “Reactions — build state from other state”

A reaction derives fields from other state. It watches one slice and, when that changes, runs a function inside Immer to update other fields on the same store. Reactions run before any subscribers are notified, so the derived fields are always up to date within a single render.

interface IState {
count: number;
doubled: number; // derived — never written by hand
history: number[]; // derived
}
const store = new Store<IState>({ count: 0, doubled: 0, history: [] });
store.createReaction(
(s) => s.count, // watch
(count, draft) => { // derive
draft.doubled = count * 2;
draft.history = [...draft.history, count].slice(-12);
},
{ runNow: true }, // run once immediately to seed derived state
);

createReaction returns a disposer to remove the reaction.

watch follows a slice of state and runs your callback only when that slice actually changes. Use it for logging, saving to storage, or keeping non-React code in sync.

const unsubscribe = store.watch(
(s) => s.count,
(count, allState, previousCount) => {
console.log(`count: ${previousCount} → ${count}`);
},
);

The low-level store.subscribe(() => { ... }) runs on every update, with no slice and no arguments. The React adapter is built on it.

APIRuns whenUse it for
createReactiona watched slice changesbuilding more state onto the same store
watcha watched slice actually changesside-effects (logging, saving, syncing)
subscribeevery updatethe low-level building block; for writing adapters