Bidev
AdvancedNavigation & Routing

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.