Custom FlutterHooks Not Disposed or Duplicated with GoRouter and AdaptiveScaffold #351
-
Context flutter_adaptive_scaffold: 0.1.3
flutter_hooks: 0.18.6
go_router: 6.5.5 I'm trying to use FlutterHooks to manage the local states of a Widget, but it seems like I'm not using them correctly. In the first example, the FlutterHooks never call the void dispose() method, which leads me to believe that all hook instances are alive and never deleted. main.dartimport 'package:flutter/material.dart';
import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
final goRoutes = [
GoRoute(
path: '/',
pageBuilder: (context, state) {
return const MaterialPage(child: Page());
}),
GoRoute(
path: '/settings',
pageBuilder: (context, state) {
return const MaterialPage(child: Page());
}),
];
void main() {
final goRouter = GoRouter(
routes: goRoutes,
debugLogDiagnostics: true,
);
runApp(MyApp(goRouter));
}
class MyApp extends StatelessWidget {
final GoRouter goRouter;
MyApp(this.goRouter);
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerDelegate: goRouter.routerDelegate,
routeInformationParser: goRouter.routeInformationParser,
// Other MaterialApp properties
);
}
}
class Page extends HookWidget {
const Page({super.key});
@override
Widget build(BuildContext context) {
final goRouter = GoRouter.of(context);
final index = goRouter.location == '/' ? 0 : 1;
final selectedIndex = useState(index);
use(const UseLogger(
initMessage: 'Hook initialized',
disposeMessage: 'Hook disposed',
));
final destinations = [
const NavigationDestination(
label: 'Home',
icon: Icon(Icons.home),
),
const NavigationDestination(
label: 'Settings',
icon: Icon(Icons.settings),
),
// Add more destinations as needed
];
return AdaptiveScaffold(
destinations: destinations,
selectedIndex: selectedIndex.value,
onSelectedIndexChange: (index) {
if (index == 1) {
goRouter.push('/settings');
selectedIndex.value = 1;
} else {
goRouter.push('/');
selectedIndex.value = 0;
}
},
);
}
}
// Custom Hook
class UseLogger extends Hook<void> {
const UseLogger({required this.initMessage, required this.disposeMessage});
final String initMessage;
final String disposeMessage;
@override
_UseLoggerState createState() => _UseLoggerState();
}
class _UseLoggerState extends HookState<void, UseLogger> {
@override
void initHook() {
super.initHook();
print(hook.initMessage);
}
@override
void dispose() {
print(hook.disposeMessage);
super.dispose();
}
@override
void build(BuildContext context) {}
} Here are the logs when I switch pages; we can see that [GoRouter] setting initial location null
flutter: Hook initialized
[GoRouter] pushing /settings
flutter: Hook initialized
[GoRouter] pushing /
flutter: Hook initialized
[GoRouter] pushing /settings
flutter: Hook initialized
[GoRouter] pushing /
flutter: Hook initialized
[GoRouter] pushing /settings
flutter: Hook initialized This issue might be caused by GoRouter always creating a new Page without deleting the previous one. Is there a way to handle this situation? In the second example, FlutterHooks do call the In this example, I use main.dartimport 'package:flutter/material.dart';
import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
final goRoutes = [
GoRoute(
path: '/',
pageBuilder: (context, state) {
return const MaterialPage(child: Page());
}),
GoRoute(
path: '/settings',
pageBuilder: (context, state) {
return const MaterialPage(child: Page());
}),
];
void main() {
final goRouter = GoRouter(
routes: goRoutes,
debugLogDiagnostics: true,
);
runApp(MyApp(goRouter));
}
class MyApp extends StatelessWidget {
final GoRouter goRouter;
MyApp(this.goRouter);
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerDelegate: goRouter.routerDelegate,
routeInformationParser: goRouter.routeInformationParser,
// Other MaterialApp properties
);
}
}
class Page extends StatelessWidget {
const Page({super.key});
@override
Widget build(BuildContext context) {
final goRouter = GoRouter.of(context);
final index = goRouter.location == '/' ? 0 : 1;
final selectedIndex = ValueNotifier<int>(index);
final destinations = [
const NavigationDestination(
label: 'Home',
icon: Icon(Icons.home),
),
const NavigationDestination(
label: 'Settings',
icon: Icon(Icons.settings),
),
// Add more destinations as needed
];
return AdaptiveScaffold(
destinations: destinations,
selectedIndex: selectedIndex.value,
onSelectedIndexChange: (index) {
if (index == 1) {
goRouter.push('/settings');
selectedIndex.value = 1;
} else {
goRouter.push('/');
selectedIndex.value = 0;
}
},
body: (_) => ValueListenableBuilder<int>(
valueListenable: selectedIndex,
builder: (context, index, child) {
if (index == 0) {
return const HomePage();
} else {
return const SettingsPage();
}
},
),
);
}
}
class HomePage extends HookWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
use(const UseLogger(
initMessage: 'Home Hook initialized',
disposeMessage: 'Home Hook disposed',
));
return const Center(child: Text('Home Page'));
}
}
class SettingsPage extends HookWidget {
const SettingsPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
use(const UseLogger(
initMessage: 'Settings Hook initialized',
disposeMessage: 'Settings Hook disposed',
));
return const Center(child: Text('Settings Page'));
}
}
// Custom Hook
class UseLogger extends Hook<void> {
const UseLogger({required this.initMessage, required this.disposeMessage});
final String initMessage;
final String disposeMessage;
@override
_UseLoggerState createState() => _UseLoggerState();
}
class _UseLoggerState extends HookState<void, UseLogger> {
@override
void initHook() {
super.initHook();
print(hook.initMessage);
}
@override
void dispose() {
print(hook.disposeMessage);
super.dispose();
}
@override
void build(BuildContext context) {}
} Log
In this part I don't understand very well how it's possible. My goal being that the hooks "init/dispose" when opening and closing pages without duplicating. Do you have any tips for doing this? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Pop those pages.
If you're expecting state to be shared between routes, that's not hooks you're looking for, but something like Riverpod. Hooks are nothing but a different way of writing StatefulWidgets. You would have the exact same issues with StatefulWidgets. |
Beta Was this translation helpful? Give feedback.
Pop those pages.
This is unrelated to hooks :)
If you're expecting state to be shared between routes, that's not hooks you're looking for, but something like Riverpod.
Hooks are nothing but a different way of writing StatefulWidgets. You would have the exact same issues with StatefulWidgets.