2

Normally you would have a Scaffold with its own AppBar on every page, but why is that needed with go_router? Why can't you just have a single Scaffold with an AppBar and let that handle navigation.

Going to the SecondScreen in this example won't update the AppBar and show the back button.

Why is this not possible?

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

void main() => runApp(const MyApp());

final GoRouter _router = GoRouter(
  routes: <RouteBase>[
    ShellRoute(
      builder: (context, state, child) {
        return Scaffold(
          body: child,
          appBar: AppBar(
            title: const Text('Test'),
          ),
        );
      },
      routes: [
        GoRoute(
          path: '/',
          pageBuilder: ((context, state) => const NoTransitionPage(
                child: HomeScreen(),
              )),
          routes: [
            GoRoute(
              path: 'second',
              pageBuilder: ((context, state) => const NoTransitionPage(
                    child: SecondScreen(),
                  )),
            ),
          ],
        ),
      ],
    ),
  ],
);

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        onPressed: () => context.go('/second'),
        child: const Text('Go to the Second screen'),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  const SecondScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text('Second screen'),
    );
  }
}
krishnaacharyaa
  • 14,953
  • 4
  • 49
  • 88
Keetz
  • 63
  • 8

1 Answers1

0

Edit: SecondScreen in this example won't update the AppBar and show the back button :

Because you are using the same appBar for all the child compnents. The main purpose of the ShellRoute is have same appBar. For it to have backButton it cannot have same appBar. The appBar should change.Which violates the usage of ShellRoute

For you to have backbutton you should navigate from ShellRoute to GoRoute or GoRoute to ShellRoute , Withtin the ShellRoute back button is not possible as it creates a shell around its children. So having backbutton inside the ShellRoute would defeat the purpose of having a same appBar throughout.


There are two corrections

  1. change second to /second
 GoRoute(
    path: '/second',  Change to this
    pageBuilder: ((context, state) => const NoTransitionPage(
          child: SecondScreen(),
        )),
    ),
  1. For appBar to be having backbutton use context.push('/second') instead of context.go('/second')
  - context.go('/second')    // Used to replace a page
  - context.push('/second')  // Used to push a page to navigation stack.
 child: ElevatedButton(
        onPressed: () => context.push('/second'),  //  change it to push
        child: const Text('Go to the Second screen'),
      ),

Refer this examples:

  1. How to change the app bar title depending on the selected GoRouter route?
  2. How to Use Shell Route with GoRoute in same hierarchy Routes
krishnaacharyaa
  • 14,953
  • 4
  • 49
  • 88
  • If I change the path to '/second' it throws an error ```Assertion failed: file:///home/rke/.pub-cache/hosted/pub.dartlang.org/go_router-6.0.1/lib/src/configuration.dart:40:18 ../…/src/configuration.dart:40 !route.path.startsWith('/') && !route.path.endsWith('/') "sub-route path may not start or end with /: GoRoute(name: null, path: /second)"``` and using push instead of go doesn't help, still no back button in the AppBar after going to SecondScreen – Keetz Jan 05 '23 at 15:00
  • try to restart , and SecondScreen should have appBar: Appbar() in its scaffold for the back button to be visible – krishnaacharyaa Jan 05 '23 at 15:03
  • But my question is, why is the Scaffold needed in the SecondScreen? Why is it needed to create Scaffolds on all pages in my application with go router? I was hoping that it was possible to build a single scaffold with an AppBar that works across all pages, like you would normally do in flutter. – Keetz Jan 05 '23 at 15:04
  • Because you are placing it wrongly, Your single Scaffold should be inside the ShellRoute, wait let me update my answer – krishnaacharyaa Jan 05 '23 at 15:06
  • Please see the example in my updated post. And just change context.go('home') to context.push('home') for back button to be visible.Hope it helps. – krishnaacharyaa Jan 05 '23 at 15:10
  • I have seen your exact same answer on other questions, I can't seem to find the connection. My Scaffold and AppBar is inside my ShellRoute. Your edited answer is fine for having something like a bottom navigation bar that shouldn't update when the "shell" changes, but my case is that I want to functionality of the back button that an AppBar normally gives, but in go router I can only get it to work if I create an Scaffold with an AppBar on EVERY single page, I was hoping that I could have a single Scaffold with a single AppBar. – Keetz Jan 05 '23 at 15:12
  • You must be missing passing of child to ScaffoldAppAndBottomBar, dont forget that – krishnaacharyaa Jan 05 '23 at 15:21
  • I appreciate your help Krishna, but could you please try and run my code example, just press the "Go to the Second screen" button and you can immediately see that there won't be a back button in the AppBar. I am using ShellRoute, I do create my Scaffold in the ShellRoute, I do pass the child to the Scaffolds body. – Keetz Jan 05 '23 at 15:24
  • the problem is you are trying to go to nested route – krishnaacharyaa Jan 05 '23 at 15:25
  • [Come to this link](https://chat.stackoverflow.com/rooms/250872/discussion-between-keetz-and-krishna-acharya) – krishnaacharyaa Jan 05 '23 at 15:28