csells / go_router

The purpose of the go_router for Flutter is to use declarative routes to reduce complexity, regardless of the platform you're targeting (mobile, web, desktop), handling deep linking from Android, iOS and the web while still allowing an easy-to-use developer experience.
https://gorouter.dev
441 stars 96 forks source link

[BUG] context.pop() removes all redirected routes in GoRoute #346

Closed II11II closed 2 years ago

II11II commented 2 years ago

If we redirect from GoRouter to /3/4, user in 4 route and user send action context.pop() then go_router removes 4 route and user in 3 route, then user sends action context.pop() one more time it removes 3 route, which is expected behaviour in the normal app.

But if redirect from GoRoute to /3/4, user in 4 route and user send action context.pop() then go_router removes 4 and 3 routes

Minimum code to reproduce this bug:

late final _router = GoRouter(
    routes: [
      GoRoute(
        path: '/',
        builder: (context, state) => Builder(builder: (context) {
          return Scaffold(
            appBar: AppBar(),
            floatingActionButton: FloatingActionButton(
              onPressed: () {
                context.push('/2');
              },
              child: Text('/'),
            ),
          );
        }),
      ),
      GoRoute(
        path: '/2',
        builder: (context, state) => Builder(builder: (context) {
          return Scaffold(
            appBar: AppBar(),
            floatingActionButton: FloatingActionButton(
              onPressed: () {
                context.push('4');
              },
              child: Text('/'),
            ),
          );
        }),
        redirect: (_) => '/3/4',
      ),
      GoRoute(
        path: '/3',
        builder: (context, state) => Builder(builder: (context) {
          return Scaffold(
            appBar: AppBar(),
            floatingActionButton: FloatingActionButton(
              onPressed: () {
                context.push('/4');
              },
              child: Text('/'),
            ),
          );
        }),
        routes: [
          GoRoute(
            path: '4',
            builder: (context, state) => Builder(builder: (context) {
              return Scaffold(
                appBar: AppBar(),
                floatingActionButton: FloatingActionButton(
                  onPressed: () {
                    context.pop();
                  },
                  child: Text('pop'),
                ),
              );
            }),
          )
        ],

      ),

    ],

    // show the current router location as the user navigates page to page; note
    // that this is not required for nested navigation but it is useful to show
    // the location as it changes
    navigatorBuilder: (context, state, child) => Material(
      child: Column(
        children: [
          Expanded(child: child),
          Padding(
            padding: const EdgeInsets.all(8),
            child: Text(state.location),
          ),
        ],
      ),
    ),
  );
csells commented 2 years ago

@II11II can you provide a complete running app? that helps me to debug. thanks!

II11II commented 2 years ago
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  App({Key? key}) : super(key: key);

  static const title = 'GoRouter Example: Declarative Routes';

  @override
  Widget build(BuildContext context) => MaterialApp.router(
        routeInformationParser: _router.routeInformationParser,
        routerDelegate: _router.routerDelegate,
        title: title,
      );
  late final _router = GoRouter(
    routes: [
      GoRoute(
        path: '/',
        builder: (context, state) => Builder(builder: (context) {
          return Scaffold(
            appBar: AppBar(),
            floatingActionButton: FloatingActionButton(
              onPressed: () {
                context.push('/2');
              },
              child: Text('/'),
            ),
          );
        }),
      ),
      GoRoute(
        path: '/2',
        builder: (context, state) => Builder(builder: (context) {
          return Scaffold(
            appBar: AppBar(),
            floatingActionButton: FloatingActionButton(
              onPressed: () {
                context.push('4');
              },
              child: Text('/'),
            ),
          );
        }),
        redirect: (_) => '/3/4',
      ),
      GoRoute(
        path: '/3',
        builder: (context, state) => Builder(builder: (context) {
          return Scaffold(
            appBar: AppBar(),
            floatingActionButton: FloatingActionButton(
              onPressed: () {
                context.push('/4');
              },
              child: Text('/'),
            ),
          );
        }),
        routes: [
          GoRoute(
            path: '4',
            builder: (context, state) => Builder(builder: (context) {
              return Scaffold(
                appBar: AppBar(),
                floatingActionButton: FloatingActionButton(
                  onPressed: () {
                    context.pop();
                  },
                  child: Text('pop'),
                ),
              );
            }),
          )
        ],

      ),

    ],

    // show the current router location as the user navigates page to page; note
    // that this is not required for nested navigation but it is useful to show
    // the location as it changes
    navigatorBuilder: (context, state, child) => Material(
      child: Column(
        children: [
          Expanded(child: child),
          Padding(
            padding: const EdgeInsets.all(8),
            child: Text(state.location),
          ),
        ],
      ),
    ),
  );
}