Open
Description
GoRouter's canPop method gives out of date results until the following frame after the navigation.
Steps to reproduce
- Run the app below, which listens to GoRouter and logs its state.
- Navigate to the next route.
Expected:
When GoRouter's listener is called, its canPop
is true, because there are two routes on the stack.
GoRouter changed. Location: /one. canPop? true
After the post frame callback. Location: /one. canPop? true
Actual:
GoRouter's listener is called, and the location
is correct, but canPop
is still out of date and gives false. After a post frame callback, it is up to date and returns true.
GoRouter changed. Location: /one. canPop? false
After the post frame callback. Location: /one. canPop? true
Example app
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/scheduler.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(_MyApp());
class _MyApp extends StatefulWidget {
@override
State<_MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<_MyApp> {
final GoRouter _router = GoRouter(
routes: <RouteBase>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) => _LinksPage(
title: 'Home page',
backgroundColor: Colors.indigo,
buttons: <Widget>[
TextButton(
onPressed: () {
context.push('/one');
},
child: const Text('Go to one'),
),
],
),
),
GoRoute(
path: '/one',
builder: (BuildContext context, GoRouterState state) => _LinksPage(
title: 'Page one',
backgroundColor: Colors.indigo.withRed(255),
buttons: <Widget>[
TextButton(
onPressed: () {
context.push('/one/two');
},
child: const Text('Go to one/two'),
),
],
),
),
GoRoute(
path: '/one/two',
builder: (BuildContext context, GoRouterState state) => _LinksPage(
title: 'Page one/two',
backgroundColor: Colors.indigo.withBlue(255),
),
),
],
);
void _routerChanged() {
print('GoRouter changed. Location: ${_router.location}. canPop? ${_router.canPop()}');
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
print('After the post frame callback. Location: ${_router.location}. canPop? ${_router.canPop()}');
SystemNavigator.updateNavigationStackStatus(_router.canPop());
});
}
@override
void initState() {
super.initState();
_router.addListener(_routerChanged);
}
@override
void dispose() {
_router.removeListener(_routerChanged);
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: _router,
);
}
}
class _LinksPage extends StatelessWidget {
const _LinksPage ({
required this.backgroundColor,
this.buttons = const <Widget>[],
required this.title,
});
final Color backgroundColor;
final List<Widget> buttons;
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: backgroundColor,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(title),
...buttons,
if (GoRouter.of(context).canPop())
TextButton(
onPressed: () {
context.pop();
},
child: const Text('Go back'),
),
],
),
),
);
}
}
Filed this issue after discovering while working on predictive back and talking to @chunhtai offline.
john-regalado-novade, AhmedLSayed9, tenhobi, ryzizub and Kuhlemann
Metadata
Metadata
Assignees
Labels
Important issues not at the top of the work listImportant issues not at the top of the work listFound to occur in 3.10Found to occur in 3.10Found to occur in 3.7Found to occur in 3.7The issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onThe go_router packageThe go_router packageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.Owned by Framework teamOwned by Framework teamTriaged by Framework teamTriaged by Framework team