-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Steps to reproduce
Steps:
- go_router: v12.1.3
- Launch sample
- Press 'Push And Pop" button
Explanation:
This issue occurs when pushing and popping pages rapidly enough. Adding a delay of 100-200ms seems to fix the issue, but this is not an optimal solution in my opinion. It's more of a hack that unnecessarily delays app interactions in the hope of avoiding the bug.
Here's an example use case for this issue and why you might need to pop a newly pushed page very quickly. A good use case would be when a Future completes fast enough, like so:
router.pushPageA();
final status = await future();
if (status.isSuccess) {
router.pushSomeOtherPage();
} else {
router.pop(); // close PageA
}In this example, you push PageA, await for a Future to complete, and based on the status, either push another page or pop PageA. If the Future completes quickly, the pop operation happens immediately after the push, causing the issue.
Expected results
PageB should be popped without errors.
Actual results
The error 'There is nothing to pop' occurs when attempting to pop a newly pushed PageB. A pop occurs before GoRouter is able to acknowledge the new route (PageB).
Code sample
Code sample
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
final router = GoRouter(
routes: [
GoRoute(
name: 'A',
path: '/',
builder: (_, __) => const PageA(),
),
GoRoute(
name: 'B',
path: '/B',
builder: (_, __) => const PageB(),
),
],
);
void main() => runApp(const App());
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: router,
);
}
}
class PageA extends StatelessWidget {
const PageA({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: TextButton(
onPressed: () {
context.pushNamed('B');
context.pop();
},
child: const Text('Push And Pop'),
),
),
],
),
);
}
}
class PageB extends StatelessWidget {
const PageB({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
backgroundColor: Colors.black,
);
}
}
Logs
Logs
Restarted application in 835ms.
════════ Exception caught by gesture ═══════════════════════════════════════════
The following GoError was thrown while handling a gesture:
There is nothing to pop
When the exception was thrown, this was the stack:
#0 GoRouterDelegate.pop (package:go_router/src/delegate.dart:94:5)
delegate.dart:94
#1 GoRouter.pop (package:go_router/src/router.dart:490:20)
router.dart:490
#2 GoRouterHelper.pop (package:go_router/src/misc/extensions.dart:71:65)
extensions.dart:71
#3 PageA.build.<anonymous closure> (package:offsuit/main_development.dart:46:25)
main_development.dart:46
#4 _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1183:21)
ink_well.dart:1183
#5 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:275:24)
recognizer.dart:275
#6 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:652:11)
tap.dart:652
#7 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:309:5)
tap.dart:309
#8 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:242:7)
tap.dart:242
#9 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:630:9)
recognizer.dart:630
#10 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12)
pointer_router.dart:98
#11 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:143:9)
pointer_router.dart:143
#12 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:633:13)
compact_hash.dart:633
#13 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18)
pointer_router.dart:141
#14 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7)
pointer_router.dart:127
#15 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:488:19)
binding.dart:488
#16 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:468:22)
binding.dart:468
#17 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:439:11)
binding.dart:439
#18 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:413:7)
binding.dart:413
#19 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:376:5)
binding.dart:376
#20 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:323:7)
binding.dart:323
#21 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:292:9)
binding.dart:292
#22 _invoke1 (dart:ui/hooks.dart:328:13)
hooks.dart:328
#23 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:410:7)
platform_dispatcher.dart:410
#24 _dispatchPointerDataPacket (dart:ui/hooks.dart:262:31)
hooks.dart:262
Handler: "onTap"
Recognizer: TapGestureRecognizer#832a5
debugOwner: GestureDetector
state: possible
won arena
finalPosition: Offset(226.0, 447.0)
finalLocalPosition: Offset(78.6, 19.0)
button: 1
sent tap down
════════════════════════════════════════════════════════════════════════════════Flutter Doctor output
Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.16.7, on macOS 14.2.1 23C71 darwin-arm64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.3)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.3)
[✓] VS Code (version 1.86.2)
[✓] Connected device (3 available)
[✓] Network resources