State machines have gained significant adoption for managing complex UI logic in 2026. Libraries like XState provide a formal way to model application state that eliminates entire classes of bugs.
The Problem with Ad-hoc State
// Problematic: Flags that can conflict
const [isLoading, setIsLoading] = useState(false)
const [isError, setIsError] = useState(false)
const [isSuccess, setIsSuccess] = useState(false)
// Can be loading AND error AND success simultaneously!
State Machines to the Rescue
import { createMachine, assign } from "xstate"
const fetchMachine = createMachine({
id: "fetch",
initial: "idle",
context: { data: null, error: null },
states: {
idle: { on: { FETCH: "loading" } },
loading: {
invoke: {
src: "fetchData",
onDone: { target: "success", actions: assign({ data: (_, e) => e.data }) },
onError: { target: "failure", actions: assign({ error: (_, e) => e.data }) }
}
},
success: { on: { RESET: "idle" } },
failure: { on: { RETRY: "loading" } }
}
})
Benefits of State Machines
- Impossible States: Can't be loading and error at same time
- Explicit Transitions: All state changes are documented
- Visualizable: Generate state diagrams from code
- Testable: Test state transitions in isolation
When to Use State Machines
- Multi-step forms and wizards
- Complex async operations
- Authentication flows
- UI components with many states (modals, dropdowns)
XState Actor Model
XState 5 introduces the actor model for managing multiple state machines that communicate through events, perfect for complex features with multiple coordinating components.
Comments (0)
Leave a Comment
No comments yet. Be the first to share your thoughts!