How do you implement nested navigation in Flutter (e.g. a bottom nav bar with separate stacks per tab)?
Short Answer
Give each tab its own Navigator with a unique key, so each tab maintains an independent back stack, and wrap it in an IndexedStack to preserve each tab's state when switching between them.
A naive bottom-nav implementation swaps the body widget based on the selected index, resetting each tab's navigation state (and scroll position) every time you switch away and back. The fix: give each tab its own Navigator (each with a distinct GlobalKey<NavigatorState>), nested inside an IndexedStack (which keeps all tabs' widget trees alive, just hidden) — so switching tabs doesn't rebuild or reset them.
go_router's StatefulShellRoute is the modern, purpose-built solution for exactly this pattern, handling the multiple-Navigator-plus-IndexedStack wiring for you.
Code Example
IndexedStack(
index: currentTabIndex,
children: [
Navigator(key: tab1NavigatorKey, onGenerateRoute: onGenerateRoute1),
Navigator(key: tab2NavigatorKey, onGenerateRoute: onGenerateRoute2),
],
)Common Mistakes
- ×Using a plain Stack/conditional widget swap for bottom-nav tabs instead of IndexedStack, causing each tab's state and scroll position to reset on every switch.
- ×Sharing a single Navigator across all tabs, so pushing a screen in one tab affects the whole app's back button behavior instead of just that tab.