What is the most appropriate way to handle navigation with a BottomNavigationBar

I’m just starting to explore mobile app development, and I have some questions about how navigation should happen for common layouts.

Assuming we have a Material Design app with an AppBar and a BottomNavigationBar, if I open a route within a widget, should it open a new page that ALSO contains the same AppBar and BottomNavigationBar, or should my routes be replaced with logic that updates the body of the Scaffold?

Assuming a simple app:

class MainScreen extends StatefulWidget {
  @override
  MainScreenState createState() => MainScreenState();
}

class MainScreenState extends State<MainScreen> {
  int _index = 0;
  Widget view = mainScreens.elementAt(0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Main'),
      ),
      body: view,
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _index,
        type: BottomNavigationBarType.fixed,
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('Home')
          ),
          BottomNavigationBarItem(
              icon: Icon(Icons.queue),
              title: Text('List')
          ),
          BottomNavigationBarItem(
              icon: Icon(Icons.person),
              title: Text('Account')
          ),
        ],
        onTap: (index) => {
          setState(() {
            _index = index;
            view = mainScreens.elementAt(_index);
          })
        },
      ),
    );
  }
final List<Widget> mainScreens = [
  HomeScreen(),
  ListScreen(),
  AccountScreen()
];
}

In this example, my “ListScreen” contains “links” to other sections of the app, but I want the BottomNavigationBar to persist throughout the app.

I currently reach up from the ListScreen and then setState of the MainScreen to update the view variable. This however requires me to make the MainScreenState public.

...
#ListScreen:list_screen.dart
onPressed: () => {
    context.findAncestorStateOfType<MainScreenState>().setState(() {
        context.findAncestorStateOfType<MainScreenState>().view = FooBarScreen();
    })
},
...

Is this appropriate, or should this be done in some other (“better”) way?