Closed Namli1 closed 5 months ago
Fixed the problem by myself, it is indeed a problem with the setup of the nested Beamer. When doing a Hot Reload, the Beamer
widget gets rebuilt and my guess is that it then starts again at the initial path and navigates to the current path from there, thus rebuilding the SecondLocation
and causing an unwanted navigation. The fix is easy, just replace the Beamer
widget with a Material.router
, that way the path seems to be kept across rebuilds.
Working example:
import 'package:beamer/beamer.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
//Top-level BeamerDelegate
final BeamerDelegate routerDelegate = BeamerDelegate(
locationBuilder: RoutesLocationBuilder(
routes: {
'/*': (context, state, data) => const MainScreen(),
},
),
);
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerDelegate: routerDelegate,
routeInformationParser: BeamerParser(),
title: 'Beamer Bug Test',
);
}
}
class MainScreen extends StatefulWidget {
const MainScreen({super.key});
@override
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
//Nested BeamerDelegate
late final BeamerDelegate routerDelegate = BeamerDelegate(
initialPath: '/first',
locationBuilder: BeamerLocationBuilder(
beamLocations: [
SecondLocation(),
FirstLocation(),
],
),
);
@override
Widget build(BuildContext context) {
//Use MaterialApp.router instead of Beamer here
return MaterialApp.router(
routerDelegate: routerDelegate,
routeInformationParser: BeamerParser(),
);
}
}
class FirstLocation extends BeamLocation<BeamState> {
@override
List<Pattern> get pathPatterns => [
RegExp("/first"),
];
@override
void buildInit(BuildContext context) {
print("FirstLocation build init");
super.buildInit(context);
}
@override
List<BeamPage> buildPages(BuildContext context, BeamState state) => [
BeamPage(
key: const ValueKey('first'),
child: Scaffold(
body: Center(
child: ElevatedButton(
//Navigate to SecondLocation
onPressed: () =>
Beamer.of(context).beamToNamed('/first/second'),
child: const Text("Navigate"),
),
),
)),
];
}
class SecondLocation extends BeamLocation<BeamState> {
@override
List<Pattern> get pathPatterns => [
RegExp("/first/second"),
];
@override
void buildInit(BuildContext context) {
print("SecondLocation build init");
super.buildInit(context);
}
@override
List<BeamPage> buildPages(BuildContext context, BeamState state) => [
const BeamPage(
key: ValueKey('second'),
child: Scaffold(body: Placeholder()),
),
];
}
Describe the bug I have a nested Beamer where I navigate from one Location to another Location. Then upon reaching the second location, if I do a Hot Reload, the second location will rebuilt (i.e. buildInit() is called again). But this only happens once, on the second Hot Reload, the location does not rebuilt, everything keeps its state. See the example below for more details.
Beamer version: 2.0.0-dev.0 (but same problem occurs with 1.6.0)
To Reproduce Below is a minimal reproducible example, the setup is as follow:
MyApp()
widget, the top-level router delegate is configured (but in this example it just redirects to theMainScreen
. The problem only occurs when using a nested beamer.)MainScreen()
widget, the nested Beamer is set up, consisting of two locations.FirstLocation
. A widget is displayed that allows to navigate to theSecondLocation
SecondLocation
, thebuildInit()
method of theSecondLocation
is called. This is expected.buildInit()
method ofSecondLocation
is called again and there is a navigation animation. This is not the expected behaviour. No navigation was triggered, so the state should just be kept.Expected behavior After navigating to
SecondLocation
, the state should be kept and no navigation should occur when performing a Hot Reload.I am not sure if this is a problem with the setup of the nested navigation or a bug in the package itself. Any help is appreciated!