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 watches one slice of state and, when it changes, runs a function (inside Immer) to update other fields on the same store. Reactions run before any subscribers are notified, so these 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. Great 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 (no slice, no arguments) — it’s the basic building block the React adapter is built on.

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