Open justinmc opened 1 year ago
Verified on latest versions using the example code provided and can see the same reported behavior.
This might come from https://github.com/flutter/flutter/issues/119677 and be a duplicate
I think you're right!
@ValentinVignal @darshankawar The problem is not in GoRouter.canPop()
. In fact it's working correctly since Navigator.canPop()
returns false
in that moment too. You can validate it yourself:
final rootKey = GlobalKey<NavigatorState>();
class _MyAppState extends State<_MyApp> {
final GoRouter _router = GoRouter(
navigatorKey: rootKey,
...
);
void _routerChanged() {
print(
'GoRouter changed. Location: ${_router.location}. canPop? ${_router.canPop()}. nav.canPop? ${rootKey.currentState?.canPop()}');
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
print(
'After the post frame callback. Location: ${_router.location}. canPop? ${_router.canPop()}. nav.canPop? ${rootKey.currentState?.canPop()}');
});
}
}
it is that the goRouter notify its listener one frame early, the route change will take one frame to propagate the change to navigator before its canPop will change.
Hey :) Is there any update on this? I'm trying to add a back button to pages where canPop is true - for the first route in a stack I'm getting canPop = false
on first render.
Eg for Sub routes a b and c...
initial route /a
correctly returns canPop = false
navigating to /a/b
also returns canPop = false
on first render so the back button isn't displayed (incorrectly as obviously we can go back to /a
now)
Navigating another level to /a/b/c
we see the back button is visible as canPop = true
(I assume due to now picking up on the previous route?)
Clicking the back button to go back to /a/b
then puts you back to the second screen but now canPop = true
on first render and the back button correctly appears
Hey :) Is there any update on this? I'm trying to add a back button to pages where canPop is true - for the first route in a stack I'm getting
canPop = false
on first render. Eg for Sub routes a b and c... initial route/a
correctly returnscanPop = false
navigating to/a/b
also returnscanPop = false
on first render so the back button isn't displayed (incorrectly as obviously we can go back to/a
now) Navigating another level to/a/b/c
we see the back button is visible ascanPop = true
(I assume due to now picking up on the previous route?) Clicking the back button to go back to/a/b
then puts you back to the second screen but nowcanPop = true
on first render and the back button correctly appears
class NaviBackButton extends StatefulWidget {
const NaviBackButton({
super.key,
});
@override
State<NaviBackButton> createState() => _NaviBackButtonState();
}
class _NaviBackButtonState extends State<NaviBackButton> {
late bool _canPop = context.canPop();
@override
Widget build(BuildContext context) {
// https://github.com/flutter/flutter/issues/124637
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
setState(() {
_canPop = context.canPop();
});
});
return IconButton(
onPressed: _canPop ? () => context.pop() : null,
icon: const Icon(Icons.chevron_left, size: 24),
);
}
}
GoRouter's canPop method gives out of date results until the following frame after the navigation.
Steps to reproduce
Expected: When GoRouter's listener is called, its
canPop
is true, because there are two routes on the stack.Actual: GoRouter's listener is called, and the
location
is correct, butcanPop
is still out of date and gives false. After a post frame callback, it is up to date and returns true.Example app
```dart // 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:Filed this issue after discovering while working on predictive back and talking to @chunhtai offline.