Editor's Note: This blog highlights Charlotte, a React Native Tech Lead at Feodo Apps, as she delves into the intricacies of React Navigation. By integrating state machines and custom navigators, she demonstrates how to streamline complex app flows, making navigation simpler and more efficient for developers.
Hi everyone, Iโm Charlotte, a React Native Tech Lead at Feodo apps, and today weโre diving into a topic that impacts all of usโflows. Flows are the backbone of many apps, from onboarding sequences to complex payment funnels. But when these flows grow in complexity, they can become an overwhelming challenge for developers.
When Simplicity Turns Complex
Most apps have flowsโa structured sequence of pages where we control the userโs journey. In a perfect world, this structure would remain manageable, but as complexity creeps in, itโs easy for the code to become convoluted. I faced this firsthand when I joined a new project with already implemented flows. My task? Add a simple page to an existing flow.
It sounded easy, right? However, the reality was far from it. The flowโs code had grown into a tangled mess. The challenge wasnโt just adding a pageโit was deciphering the logic hidden beneath layers of complexity. As the sole developer tasked with this, I found myself lost in the maze of navigation paths.
A Developerโs Nightmare: Complex Navigation

Fast forward a few monthsโI had the opportunity to start fresh on a new flow. This time, I was determined to make it right from the start. Today, I want to share how we leveraged the power of state machines to clarify React Navigation and simplify even the most complex flows.
But before we dive into the solution, letโs take a step back and define what we mean by โflows.โ
What Exactly is a Flow?
A flow is a predetermined series of pages where the userโs path is predefined, like an onboarding sequence or checkout process. Unlike regular navigation, where users are free to jump from page to page, a flow guides users along a set path, ensuring they click "Next" to reach the subsequent step.
However, things can get messy when logic and conditions start piling up within a flow.
The Hidden Problem of Complex Flows

Consider the flow I had to implementโit looked simple on the surface, but was riddled with conditions and logic. The problem? Using regular page-to-page navigation for such a flow made it almost impossible to get a clear overview of the entire sequence. You had to dive into every page to understand the navigation paths hidden within conditional logic. This made debugging and adding new steps a developerโs nightmare.
So how do we fix this? How can we write code that screams, โThese are all the possible pathways!โ?
The Ideal Flow Solution: State Machines to the Rescue
Imagine an ideal solutionโa system where you can see the entire flow in one place. A system where pages donโt have to โknowโ which page comes next. Sounds perfect, right?
Well, this is where state machines come in. State machines allow us to define the entire flowโevery page and every transitionโin one clear place. Letโs break it down with a simple analogy: traffic lights. A traffic light system is a state machine, where each color (red, yellow, green) represents a state, and transitions occur based on predefined events.
In a flow, our states are our pages. Each time the user clicks "Next," we send an event that transitions to the next page. This way, all the logic and pathways are stored in one placeโeasy to read and understand.
The First Step: Implementing State Machines in React Native

Letโs visualize this. We define a state machine with our flow's stepsโpages A, B, C, and D. Each time the user hits "Next," we transition from one state (page) to the next. This is a great start, but thereโs a problemโour state is split between the state machine and the navigation.
Whenever we transition states, we also need to update the navigation to display the correct page. If these two states get out of sync, we risk bugs. Itโs easy to forget a navigation update, leading to issues that are hard to track down.
The Breakthrough: Merging State and Navigation
This leads us to our next evolution: a more declarative approach. Instead of defining pages inside a traditional navigation stack, we define them based on the state machineโs value. This eliminates the need for manual navigation calls, making the flow much more robust.
But we still encountered issuesโmost notably, losing out on transition animations. And even worse, we still faced potential bugs due to configuration mistakes.
Building a Custom Navigator: A Game-Changer
And then came the breakthrough: building a custom navigator. One of my colleagues asked, "Why not create a navigator tailored to our specific needs?" And thatโs exactly what we did. By building a custom flow navigator, we were able to combine the state machine and navigation into a single, coherent system.
Let me introduce you to the Flow Navigator.
The Flow Navigator: Simplifying Complex Logic
The Flow Navigator looks and behaves like a regular navigator but with one critical differenceโyou define the flowโs order in one place. Hereโs an example: cart review, payment, success. In one glance, you can see the entire flow and its order. And inside each page, like Cart Review, you simply call a methodโgoToNextStepโto advance to the next page without worrying about its position in the flow.
Internally, this works through an index that tracks which page is currently active. As the user moves through the flow, the index bumps up, ensuring seamless navigation from one step to the next.
Handling Conditional Logic with Ease
Of course, not all flows are linear. What about conditional pagesโlike a document signing step that only appears once? With the Flow Navigator, we can handle conditional logic effortlessly. For example, we use a Boolean value to determine whether the document signing page appears or not.
Once the condition is met, the page is removed from the flow, and the user moves on. This allows for dynamic, adaptive navigation based on user input or other conditions.
Limitations and Future Possibilities
The Flow Navigator solves many architectural issues, but like any solution, it has limitations. For instance, you canโt always see all the possible pathways at a glance. And while it works well with React Navigation, we havenโt built it for Explore Router yet. However, these are challenges we are actively working on.
Rethinking Flow Architectures
Today, we explored how state machines can transform complex flows into clear, manageable systems. By building custom navigators like the Flow Navigator, weโve created a tool that makes navigating complex flows easier and more intuitive.
I hope this reflection on flow architecture has inspired you to think about your own appโs navigation in new ways. Next time you face scattered logic, remember the power of state machines and custom navigatorsโthey could be your key to clarity and simplicity.







