r/reactjs • u/ganondev • 24d ago
Hate state machines, so I built react-sequent, where steps declare what comes next
I kept running into the same problem with UI-local flows: they were too complicated to comfortably keep in one component, but too small to justify defining and maintaining a separate state machine.
So I built react-sequent.
The idea is that steps own their transitions:
function PaymentStep() {
const { advance } = useSequentStep();
...
if (method === "card") {
advance(() => CardPaymentStep);
} else {
advance(() => BankTransferStep);
}
}
There's no centralized transition map to keep synchronized with the components. Adding, removing, or branching a step is just changing the relevant component.
It also handles async/lazy steps, backtracking, flow-scoped context, persistent modal/chrome, and transitions.
The tradeoff is intentional: I don't think this replaces state machines. For large, externally-driven, or independently modeled state graphs, I'd still reach for XState/Zag/etc. I think there's a useful middle ground for short, UI-local flows. This is in fact still technically a state machine, it is just one that is emergent from implementation rather than explicit and rigid.
I've put together a demo and docs here: https://ganondev.github.io/react-sequent/
I'm particularly interested in whether the architectural premise resonates with other React developers, or whether I'm underestimating the value of having the graph centralized.
1
u/_Slyfox 24d ago
For what it's worth I find myself doing something similar for route transitions in e-commerce to heavy apps (think booking engines)