-
Notifications
You must be signed in to change notification settings - Fork 30.2k
[go_router] Navigating back from a sub-route to the parent route does not call "redirect" #145173
Copy link
Copy link
Closed as not planned
Closed as not planned
Copy link
Labels
r: duplicateIssue is closed as a duplicate of an existing issueIssue is closed as a duplicate of an existing issue
Description
Steps to reproduce
- Run this gist: https://dartpad.dev/?id=fbfa675230ed6e129f45ee7c22665a44
- Tap /bar/baz, redirect is called and stays on /foo
- Toggle on the switch at the bottom so it's on
- Tap /bar/baz again, redirect is called and navigation works fine
- Toggle on the switch at the bottom so it's off
- Navigate back
- You can navigate fine, redirect is NOT called
Expected results
redirect should always be called when navigating to a different route.
Actual results
redirect is not called when navigating back to parent route from child route.
Note that this is the same as reported in #101183
That issue was closed as merged but this problem persists.
Code sample
Code sample
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
void main() => runApp(const AllowedWidget(child: MyApp()));
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late final GoRouter _router;
@override
void dispose() {
_router.dispose();
super.dispose();
}
@override
Widget build(context) {
final allow = InheritedAllowedWidget.of(context).notifier;
_router = GoRouter(
routes: <GoRoute>[
GoRoute(path: '/', redirect: (BuildContext context, GoRouterState state) => '/foo'),
GoRoute(
path: '/foo',
builder: (context, state) => MyPage(
key: state.pageKey,
nexts: const ['/bar', '/bar/baz'],
),
),
GoRoute(
path: '/bar',
builder: (context, state) => MyPage(
key: state.pageKey,
nexts: const ['/bar/baz'],
),
routes: [
GoRoute(
path: 'baz',
builder: (context, state) => MyPage(
key: state.pageKey,
nexts: const ['/foo'],
),
),
],
),
],
redirect: (BuildContext context, GoRouterState state) {
print('redirect called');
return allow.value ? null : '/foo';
},
);
return MaterialApp.router(
routeInformationProvider: _router.routeInformationProvider,
routeInformationParser: _router.routeInformationParser,
routerDelegate: _router.routerDelegate,
);
}
}
class MyPage extends StatelessWidget {
final Iterable<String> nexts;
const MyPage({
required this.nexts,
Key? key,
}) : super(key: key);
@override
Widget build(context) {
final allow = InheritedAllowedWidget.of(context).notifier;
return Scaffold(
appBar: AppBar(
title: Text(GoRouter.of(context).routerDelegate.currentConfiguration.uri.toString()),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (final next in nexts)
Center(
child: TextButton(
child: Text(next),
onPressed: () => context.go(next),
),
),
Center(
child: ValueListenableBuilder<bool>(
valueListenable: allow,
builder: (context, allowed, _) => Switch(
value: allowed,
onChanged: (value) => allow.value = value,
),
),
),
],
),
);
}
}
class InheritedAllowedWidget extends InheritedWidget {
const InheritedAllowedWidget({
Key? key,
required this.notifier,
required Widget child,
}) : super(
key: key,
child: child,
);
final ValueNotifier<bool> notifier;
static InheritedAllowedWidget of(BuildContext context) {
final InheritedAllowedWidget? result =
context.dependOnInheritedWidgetOfExactType<InheritedAllowedWidget>();
assert(result != null, 'No InheritedAllowedWidget found in context');
return result!;
}
@override
bool updateShouldNotify(InheritedAllowedWidget oldWidget) =>
notifier.hashCode != oldWidget.notifier.hashCode;
}
class AllowedWidget extends StatefulWidget {
final Widget child;
const AllowedWidget({
required this.child,
Key? key,
}) : super(key: key);
@override
State<AllowedWidget> createState() => _AllowedWidgetState();
}
class _AllowedWidgetState extends State<AllowedWidget> {
late final ValueNotifier<bool> _notifier;
@override
void initState() {
_notifier = ValueNotifier(false);
super.initState();
}
@override
void dispose() {
_notifier.dispose();
super.dispose();
}
@override
Widget build(context) => InheritedAllowedWidget(
notifier: _notifier,
child: widget.child,
);
}
Screenshots or Video
Screenshots / Video demonstration
Logs
Logs
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.16.9, on Ubuntu 20.04.1 LTS 5.8.18-050818-generic, locale en_IE.UTF-8)
• Flutter version 3.16.9 on channel stable at /media/sw/sdk/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 41456452f2 (7 weeks ago), 2024-01-25 10:06:23 -0800
• Engine revision f40e976bed
• Dart version 3.2.6
• DevTools version 2.28.5
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
• Android SDK at /media/sw/sdk/Android/sdk
• Platform android-34, build-tools 33.0.1
• ANDROID_HOME = /media/sw/sdk/Android/sdk
• ANDROID_SDK_ROOT = /media/sw/sdk/Android/sdk
• Java binary at: /media/sw/sdk/android-studio/jbr/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)
• All Android licenses accepted.
[✓] Chrome - develop for the web
• Chrome at google-chrome
[✓] Linux toolchain - develop for Linux desktop
• clang version 10.0.0-4ubuntu1
• cmake version 3.18.3
• ninja version 1.10.0
• pkg-config version 0.29.1
[✓] Android Studio (version 2022.1)
• Android Studio at /media/sw/sdk/android-studio
• Flutter plugin version 72.0.2
• Dart plugin version 221.6096
• Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)
[✓] VS Code (version 1.86.1)
• VS Code at /usr/share/code
• Flutter extension version 3.84.0
[✓] Connected device (3 available)
• RMO NX1 (mobile) • LLL • android-arm64 • Android 13 (API 33)
• Linux (desktop) • linux • linux-x64 • Ubuntu 20.04.1 LTS 5.8.18-050818-generic
• Chrome (web) • chrome • web-javascript • Google Chrome 109.0.5414.119
[✓] Network resources
• All expected network resources are available.
• No issues found!Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
r: duplicateIssue is closed as a duplicate of an existing issueIssue is closed as a duplicate of an existing issue