Closed theweiweiway closed 2 years ago
Having same issue. Did u find a fix yet?
I think 2.1.1 has some additional features to help with this - will test out later today
I think 2.1.1 has some additional features to help with this - will test out later today
I'm using 2.2.0 version. Same error, Pages stack can be managed by either the Widget (AutoRouter.declarative) or Router.
[VERBOSE-2:ui_dart_state.cc(199)] Unhandled Exception: 'package:auto_route/src/router/controller/routing_controller.dart': Failed assertion: line 838 pos 7: '!managedByWidget': Pages stack can be managed by either the Widget (AutoRouter.declarative) or Router
Got the same problem, so I can't push signup page from login page.
No one fix that error, I'm facing it also
Has anyone fixed this issue?
@ArintonAkos @simofilahi @2shrestha22 you're seeing this assertion message because you're trying to push routes to a declarative router. routers can either be used imperatively ( push, replace ..etc) or declaratively, you can not use both methods on the same router.
I've got the same problem. How did you fix it ?
@Milad-Akarie Hi, I'm a bit beginner with AutoRoute but it has been awesome so far. The declarative approach seems perfect for adding onboarding+loading screen to my app, however the rest of my app is using the imperative approach. How do I go about supporting both, I believe I need to use 2 routers or something but not sure.
MaterialApp.router(
debugShowCheckedModeBanner: false,
routerDelegate: appRouter.declarativeDelegate(
routes: (_) => [
if (!widget.doneOnboarding)
OnboardingRoute(onFinishedOnboarding: onFinishedOnboarding)
else if (!ref.watch(isAuthenticatedProvider).state) LoadingRoute()
else HomeRoute(), <-- using rcontext.router.push() here fails
],
),
...
@AdaptiveAutoRouter(
replaceInRouteName: 'Page,Route',
routes: <AutoRoute>[
AutoRoute(path: '/onboarding', page: OnboardingPage),
AutoRoute(path: '/loading', page: LoadingPage),
AutoRoute(path: '/', page: HomePage),
AutoRoute(path: '/favorite', page: FavoritePage),
...
context.router.push(FavoriteRoute());
Thanks
Same here. Using a declarative route for auth:
routes: (_) => [
if (authState == const SignedIn())
const HomeRoute()
else
const AuthWrapperRoute()
],
My home route screen is a stateless widget with a scaffold and a tab bar:
@override
Widget build(BuildContext context) => AutoTabsRouter(
routes: _routes,
builder: (context, child, animation) {
final tabsRouter = AutoTabsRouter.of(context);
return DefaultTabController(
length: _routes.length,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
actions: [
IconButton(
icon: Icon(
Icons.settings_outlined,
color: AppColors.darkGrey,
),
onPressed: () =>
context.router.push(SettingsRoute()). -> FAILS HERE
)
],
bottom: TabBar(
onTap: tabsRouter.setActiveIndex,
indicatorColor: AppColors.green,
tabs: [
Tab(
icon: Text("Tab1),
),
Tab(
icon: Text("Tab2"),
),
],
),
),
body: child,
),
);
},
);
Seems to be a common issue where you mix declarative and stack router for authentication and the content area. Some assistance from the author would be welcome
So I checked the documentation there's a helper that take the delegate auto router in the context
final router = AutoRouterDelegate.of(context);
you can use it to navigate between pages by
router.controller.navigateNamed('/route/path')
or
router.controller.navigate(SomeRouter())
@samu-developments @Milad-Akarie I got the same problem.
My entire application is using imperative way, but I need to strongly check if user is logged in, so I must use AutoRouterDelegate.declarative and this prevents me from using my app correctly as I did.
Is there any other way to implement Auth check?
I'm kinda frustrated with this. Just followed the official tutorials and I find out this issue was opened on Apr 2021 and there isn't any definitive explanation on how to solve it so far. @Milad-Akarie A solution on the problem would be very much appreciated. Thanks :)
@rafael-mq This is not a bug, this an assertion message, you can't push routes to a declarative router...it gets it's stack from the widget only.
@Milad-Akarie Although this is an open issue I get it's not a bug. But is there any possible solution for using both declarative and imperative routing? Maybe having two routers dedicated to each routing approaches just like @samu-developments suggested. Also the docs could make it clear that both approaches are not compatible. Alll in all, I congratulate the package mantainers for the outstanding work. 💯
@rafael-mq from what I understand, you can not have your declarative routing at the root of your application, unless you change your states to trigger "a push" to another route. Or if all you application is under the same AutoRoute parent as the documentation shows https://autoroute.vercel.app/advanced/authentication .
I think this design is perfect for subscription flow, when you will need to bind your state to the routing : https://autoroute.vercel.app/advanced/declarative_routing
Hope this link could help you to manage authentication
https://github.com/Milad-Akarie/auto_route_library/issues/433#issuecomment-810564956
My solution
AuthenticatedStackPage
uses declerative routing. Also the AuthenticatedStackRouter (EmptyRouterPage) is also placed inside declerative RootStackPage.
AutoRoute(
name: 'AuthenticatedStackRouter',
// Provides router for push, pop, etc.
// If we use only declerative routing we can't use these methods.
page: EmptyRouterPage,
children: [
// Authenticated root (declerative routing)
AutoRoute(
initial: true,
page: AuthenticatedStackPage,
children: [
AutoRoute(page: SetupPassPage),
AutoRoute(page: RegistrationFlowPage),
AutoRoute(page: RegistrationAdditionalStepsPage),
AutoRoute(page: HomePage),
],
),
// Other pages that could be opened only when authenticated
AutoRoute(page: SearchLocationPage),
AutoRoute(page: DiseasesListPage),
AutoRoute(page: OtherDiseasePage),
AutoRoute(page: HypertensionMedicationInfoPage),
AutoRoute(page: VaccinationInfoPage),
AutoRoute(page: VaccinationsListPage),
AutoRoute(page: ServicesListPage),
AutoRoute(page: ServiceSubcategoriesPage),
],
),
just try it like this guys:
routerDelegate: _appRouter.delegate( initialRoutes: isLoggedIn ? [const StartRoute()] : [const LoginRoute()])
My decision was to get initialDeepLink like:
if (!isAccessAllowed) {
initialDeepLink = '/app-update';
} else if (!isAuthorized) {
initialDeepLink = '/authorization';
}
return AutoRouterDelegate(
getIt<AppRouter>(),
initialDeepLink: initialDeepLink,
);
Then I wrapped my app widget with BlocConsumer, which will replace stack to AuthRoute or to MainRoute when user logged in/logged out:
return BlocConsumer<AppCubit, IAppState>(
listener: (context, state) async {
if (state is AuthorizedState) {
await getIt<AppRouter>()
.replaceAll([const NotificationsRootRoute()]);
} else if (state is UnathorizedState) {
await getIt<AppRouter>().replaceAll([AuthorizationRoute()]);
}
}
Try to embed stacked routers children into root declarative route. like this.
class RootWrapperPage extends StatelessWidget {
RootWrapperPage({Key? key}) : super(key: key);
final authProvider = ioc.get<AuthProvider>();
@override
Widget build(BuildContext context) {
return Observer(builder: (_) {
var signedIn = authProvider.signedIn;
return AutoRouter.declarative(routes: (_) => [
if (signedIn) MainWrapperRoute(),
if (!signedIn) GuestWrapperRoute(),
]);
});
}
}
@AdaptiveAutoRouter(
replaceInRouteName: 'Page,Route',
routes: <AutoRoute>[
AdaptiveRoute(
initial: true,
path: '/',
page: RootWrapperPage,
children: [
AdaptiveRoute(
path: 'guest',
page: GuestWrapperPage,
children: [
AdaptiveRoute(
initial: true,
path: 'home',
page: GuestHomePage,
),
AdaptiveRoute(
path: 'login',
page: GuestLoginPage,
),
AdaptiveRoute(
path: 'register',
page: GuestRegisterPage,
),
],
),
AdaptiveRoute(
initial: true,
path: 'main',
page: MainWrapperPage,
children: [
AdaptiveRoute(
initial: true,
path: 'home',
page: MainHomePage,
),
...
],
),
],
),
RedirectRoute(
path: "*",
redirectTo: '/',
),
],
)
class AppRouter extends _$AppRouter {
AppRouter(): super() {
...
}
}
@dehypnosis i'm trying your approach but i still get the AssertionError when I try to push new pages.
How does it work inside GuestWrapperPage
and MainWrapperPage
?
Did you leave the AutoRouter.declarative
in the MaterialApp.router
?
@dehypnosis i'm trying your approach but i still get the AssertionError when I try to push new pages. How does it work inside
GuestWrapperPage
andMainWrapperPage
? Did you leave theAutoRouter.declarative
in theMaterialApp.router
?
With 'GuestWrapperPage' also 'MainWrapperPage', you can create an empty page like this:
class GuestWrapperPage extends StatelessWidget {
GuestWrapperPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return AutoRouter();
}
}
or using EmptyRouterPage
build-in auto_route package in your route stack
@MaterialAutoRouter(
replaceInRouteName: 'Page,Route',
routes: <AutoRoute>[
AutoRoute<dynamic>(
initial: true,
path: '/',
page: RootWrapperPage,
children: [
AutoRoute<dynamic>(
path: 'authenticate',
name: 'AuthenticateRouter',
page: EmptyRouterPage,
children: [
AutoRoute<dynamic>(
initial: true,
path: 'login',
page: LoginPage,
),
AutoRoute<dynamic>(
path: 'register',
page: RegisterPage,
),
],
),
AutoRoute<dynamic>(
path: 'main',
name: 'MainWrapperRouter',
page: EmptyRouterPage,
children: [
....
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions
I have the same issue. Any updates here?
Here is how it is works EmptyRouterPage
:
If you are inside any of the OnboardWrapper
, HomeWrapper
or SplashRoute
routes you can only push their children. For example you can't push HomePage
from LoginPage
because HomePage
is from HomeWrapper
and LoginPage
is from OnboardWrapper
route. Hope it make you clear about this.
routerDelegate: AutoRouterDelegate.declarative(
appRouter,
routes: (_) {
return authState.when(
authenticated: (_) {
logger.i('Routing to HomeWrapper');
return [const HomeWrapper()];
},
unauthenticated: () {
logger.i('Routing to OnboardWrapper');
return [const OnboardWrapper()];
},
unknown: () {
logger.i('Routing to SplashRoute');
return [const SplashRoute()];
},
);
},
),
@AdaptiveAutoRouter(
replaceInRouteName: 'Page,Route',
routes: <AutoRoute>[
AutoRoute(initial: true, page: SplashPage),
AutoRoute(
page: EmptyRouterPage,
name: 'OnboardWrapper',
children: [
AutoRoute(page: OnboardPage, initial: true),
AutoRoute(page: LoginPage),
AutoRoute(page: EmailSignupPage),
AutoRoute(page: EmailOtpLoginPage),
AutoRoute(page: PhoneOtpLoginPage),
],
),
AutoRoute(
name: 'HomeWrapper',
page: EmptyRouterPage,
children: [
AutoRoute(page: HomePage, initial: true),
],
),
],
)
I have a strange problem.
When I use AutoRouterDelegate.declarative
and create an AppWrapperRoute
to solve the problem The page stack can be managed by either a widget (AutoRouter.declarative) or (StackRouter)
, my implementation of auth checking stops working and my start page is always AuthNavigationRoute
.
routerDelegate: AutoRouterDelegate.declarative(di.sl<AppRouter>(),
navigatorObservers: () =>
[TalkerRouteObserver(di.sl<Talker>())],
routes: (_) => [
(state is SignedInPageState)
? const HomeNavigationRoute()
: const AuthNavigationRoute()
]));
If I abandon the AppWrapperRoute
idea, then the auth check works correctly and if the user has already been auth, HomeNavigationRoute
opens immediately.
Also, when I try to use di.sl<AppRouter>().delegate
, my routing stops working completely and all I see is a white screen.
I would be very happy if someone could explain to me how di.sl<AppRouter>().delegate
works and what can cause the above problems.
Hey Milad,
I found a small bug when trying to match the URL with the declarative router. Overall, it works quite well! However there's a small bug that I found that should probably be fixed
Here's my app: https://github.com/theweiweiway/flutter_uxr/blob/nesting/lib/main.dart
Line 125 has the declarative router part
Basically, I have 3 routes: /settings /books/all /books/new
The /books routes are rendered declaratively as you can see in Line 125
It seems like when hitting a new fresh URL on web, the State will determine what the URL is - which makes sense - this is great. However, on the very first time I hit the /books/new URL, i get the
Pages stack can be managed by either the Widget (AutoRouter.declarative) or the (StackRouter)
error. Then, if hit that same URL again at /books/new, everything works fine and it redirects me to /books/all because the state takes overThis video basically sums everything up quite nicely: https://user-images.githubusercontent.com/49566929/116496829-eadd2900-a873-11eb-8cfa-c7dca920539c.mov
Sorry - couldn't do a gif since text was too small