Reactions & Watch
Derive state from state, and run side-effects outside React.
Reactions — derive state from state
Section titled “Reactions — derive state from state”A reaction watches a slice and, when it changes, runs a recipe inside Immer to derive further state on the same store. Reactions run before subscribers are notified, so derived fields are always consistent in 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 — side-effects outside React
Section titled “Watch — side-effects outside React”watch subscribes to a derived slice and fires only when it changes structurally. Ideal for logging, persistence, or syncing to non-React code.
const unsubscribe = store.watch( (s) => s.count, (count, allState, previousCount) => { console.log(`count: ${previousCount} → ${count}`); },);The low-level store.subscribe(() => { ... }) fires on every committed update (no slice, no args) — the primitive the React adapter builds on.
Reaction vs watch vs subscribe
Section titled “Reaction vs watch vs subscribe”| API | Fires when | Use for |
|---|---|---|
createReaction | a watched slice changes | deriving more state onto the same store |
watch | a watched slice changes structurally | side-effects (logging, persistence, sync) |
subscribe | every committed update | low-level primitive; building adapters |
Next: Patches & devtools →