I am using GoRouter
for navigation and GetX
for multiple things, including updating the app’s locale
.
It is updating the language perfectly fine, but the problem is that somehow my navigation stack is getting reset after the call.
I’ve made a Screenvideo for a better understanding but you can also test it yourself here.
I update my locale by simply calling:
Locale locale = Locale(languageCode);
await Get.updateLocale(locale);
And my routing looks like this:
final rootNavigatorKey = GlobalKey<NavigatorState>();
class AppRouter {
static final _shellNavigatorKey = GlobalKey<NavigatorState>();
static final router = GoRouter(
initialLocation: IntroView.path,
debugLogDiagnostics: true,
navigatorKey: rootNavigatorKey,
routes: [
ShellRoute(
navigatorKey: _shellNavigatorKey,
pageBuilder: (context, state, child) {
return NoTransitionPage(
child: ScaffoldView(
child: child,
),
);
},
routes: [
GoRoute(
name: ProjectsView.name,
path: '/projects',
parentNavigatorKey: _shellNavigatorKey,
pageBuilder: (context, state) {
return const FadePageTransition(
page: ProjectsView(),
);
},
routes: [
GoRoute(
parentNavigatorKey: rootNavigatorKey,
path: ':projectTitle',
pageBuilder: (context, state) {
return FadePageTransition(
page: ProjectDetailScaffold(
project: Projects.values.byName(
state.params['projectTitle']!,
),
),
);
},
),
],
),
What am I missing here?
Let me know if you need any more info!
2
Answers
For now I found a workaround that is not very clean but it works for me:
Right after I call
await Get.updateLocale(locale);
I am calling this:The problem is that
GoRouter
loses the state becauseupdateLocale
forces the app to rebuild. As workaround, I am popping all views and going to the location where I am callingupdateLocale
from.Like I said, this is no ideal and more of a workaround. If anyone know a better solution, please let me know.
Your current workaround involves essentially restarting the navigation stack and redirecting to a specific page after changing the locale, and while this might work, it does seem a bit rough and could potentially lead to user experience issues.
In Flutter, the locale change does indeed cause a rebuild of the widget tree. However, it seems unusual that the navigation stack is getting cleared in this process. Generally, the navigation stack should be maintained across rebuilds unless explicitly cleared or modified.
The issue could potentially be related to how
GetX
andGoRouter
interact with each other.GetX
is a state management solution, and it seems to be causing a full rebuild of the widget tree when the locale changes.GoRouter
on the other hand, manages navigation and should maintain its state across widget tree rebuilds.So you can try and ensure the
GoRouter
instance is not being recreated on each rebuild. The router should be created once and maintained for the duration of the app’s lifetime.And consider separating your localization and routing concerns.
Instead of calling
Get.updateLocale
directly, you could create a separate service that wraps this call and also preserves your navigation state. This service could listen for locale changes and update the locale without causing a full rebuild of the widget tree.LocaleService
is a service that wraps theGet.updateLocale
call.LocaleSwitcher
is a widget that usesGetBuilder
to listen for changes inLocaleService
, and rebuilds itself when the locale is updated.This way, only the
LocaleSwitcher
widget is rebuilt when the locale changes, not the entire widget tree.Or: consider using
GetMaterialApp
which integratesGetX
with the FlutterMaterialApp
widget (as illustrated here). This might help with preserving the navigation state when changing locale.See also "What is the difference between GetMaterialApp of GetX and MaterialApp of Flutter?".
That would also mean you are relying on
GetX
for routing instead ofGoRouter
. If you want to stick withGoRouter
for routing, the first two points are enough.However, if you are okay with transitioning to
GetX
for routing, usingGetMaterialAp
.