Flat Lifecycle Hooks API
Flat API: transitionHooks
Section titled “Flat API: transitionHooks”The transitionHooks function provides a flat, composable API for registering lifecycle hooks on a FactoryMachine. Each hook config can specify matching criteria (from, to, type) and any lifecycle phase (effect, before, after, guard, etc.).
TypeScript Friendly: All handlers are fully typed, with autocompletion for state/event keys and hook phases.
Configuration Structure
Section titled “Configuration Structure”Each entry to transitionHooks is an object with optional from, to, type keys for matching, and one or more lifecycle hook functions:
transitionHooks( { from: "Idle", type: "start", to: "Running", effect: fn, before, after }, { from: "Idle", enter: fn, leave: fn }, { type: "resolve", guard: e => true }, { effect: globalFn })You can use wildcards by omitting keys.
Example (Typechecked)
Section titled “Example (Typechecked)”setup(machine)( transitionHooks( { from: "Idle", type: "start", to: "Running", effect: fn, before, after }, { from: "Idle", enter: fn, leave: fn }, { type: "resolve", guard: e => true }, { effect: globalFn } ));Comparison: transitionHooks vs onLifecycle vs Functional Enhancers
Section titled “Comparison: transitionHooks vs onLifecycle vs Functional Enhancers”| Feature | onLifecycle (Config Object) | transitionHooks (Flat API) | Functional Enhancers (effect(whenEvent(...)), etc.) |
|---|---|---|---|
| Structure | Nested, grouped by state/event | Flat, composable, per hook | Pure, composable, per enhancer |
| Modularity | All-in-one config | Split across files/modules | Split, highly modular, functional |
| Readability | Good for grouped logic | Good for scanning hooks | Good for functional composition |
| Type Safety | Strong | Strong | Strong |
| Wildcards | ”*” keys | Omit keys | Predicate/wildcard via when/whenEvent |
| Use Case | Complex, grouped logic | Modular, scattered logic | Functional, advanced composition |
Choose onLifecycle for grouped, declarative logic.
Choose transitionHooks for modular, flat, and composable logic.
Choose functional enhancers for pure, highly composable, and advanced functional patterns.
Full Example: Mirroring onLifecycle
Section titled “Full Example: Mirroring onLifecycle”setup(machine)( transitionHooks( { from: "Idle", type: "start", to: "Running", effect: fn, before, after }, { from: "Idle", enter: fn, leave: fn }, { type: "resolve", guard: e => true }, { effect: globalFn }, { type: "tick", effect: tickEffect }, { type: "stop", effect: stopEffect }, { effect: (ev) => console.log(ev) } // global ));Alternative: Pure Functional Enhancers
Section titled “Alternative: Pure Functional Enhancers”You can also choose a more pure functional approach using raw transition hook method enhancers:
setup(machine)( enter(fn), guard(fn), leave(fn), handle(fn), // ...other enhancers)This style is ideal for highly modular or functional codebases, and can be mixed with transitionHooks or other enhancers.
See Also
Section titled “See Also”Real-World Pattern
Section titled “Real-World Pattern”For modular apps, split hooks across files and import them:
setup(machine)( ...allEnhancers, transitionHooks(...importedHooks))