英文:
context.go("/home") not working inside listener of BlocConsumer()
问题
为什么在 BlocListener 或 BlocConsumer 内部使用 context.go("/routeName") 在注册页面不起作用?
我目前正在使用 flutter_bloc
和 go_router
。 在注册页面,一旦用户提交了详细信息,我会向后端发送请求。 一旦我从后端获取到令牌,我会发出 SignupSuccessfulState
,并在注册屏幕中使用 BlocConsumer
。 当状态为 SignupSuccessfulState
时,我想将用户发送到另一页并删除所有先前的路由。 因此,在 BlocConsumer 的监听器中,我添加了 context.go("/homepage")
。 但是 context.go("")
在监听器内部不起作用,而 context.pop()
、context.push()
等选项都能正常工作。我正在使用 go_router: ^7.0.0
和 flutter_bloc: ^8.1.2
。
英文:
Why go router context.go("/routeName") is not working inside BlocListener or BlocConsumer?
i'm currently using flutter_bloc
and go router
. In the signup page once user submitted the details i'm sending a request to backend. once i got the token from backend i'm emitting the SignupSuccessfulState
& i'm using BlocConsumer
in the signup screen. when the state is SignupSuccessfulState
i want to send the user to another page and remove all the previous routes. so inside listener of BlocConsumer i added context.go("/homepage"). but context.go("")
is not working inside the listener reamining options like context.pop()
, context.push()
all are working. im using go_router: ^7.0.0
and flutter_bloc: ^8.1.2
SignupScreen.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:social/widgets/signup_screen/signup_form.dart';
import '../bloc/authentication/signup/signup_bloc.dart';
import '../widgets/common/loading_view.dart';
class SignupScreen extends StatelessWidget {
const SignupScreen({super.key});
@override
Widget build(BuildContext context) {
return Stack(
children: [
Scaffold(
appBar: AppBar(
title: const Text("Create your account"),
),
body: const SingleChildScrollView(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: SignupForm(),
),
),
),
BlocConsumer<SignupBloc, SignupState>(
listener: (context, state) {
if (state is SignupSuccessfullState) {
context.go("/signup/verification");
}
},
builder: (context, state) {
if (state is SignupLoadingState) {
return const LoadingView();
} else {
return const SizedBox.shrink();
}
},
)
],
);
}
}
SignupBloc.dart
added only event code
on<SignupRequestedEvent>(_signupRequestedEvent);
void _signupRequestedEvent(event, emit) async {
emit(SignupLoadingState(user: state.user));
final user = state.user;
try {
final String response = await authRepository.createAccount(
emailId: user.emailId,
password: event.password,
confirmPassword: event.confirmPassword,
);
if (response == "success") {
emit(
SignupInitialState(
user: user.copyWith(
emailId: "",
password: "",
confirmPassword: "",
),
),
);
emit(SignupSuccessfullState(user: state.user));
} else {
emit(SignupErrorState(user: state.user));
}
} catch (e) {
emit(SignupErrorState(user: state.user));
}
}
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:social/bloc/bloc_providers.dart';
import './theme/theme.dart';
import './utils/globals.dart';
import 'router.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
final BlocProviders blocProviders = BlocProviders();
runApp(
MultiBlocProvider(
providers: blocProviders.blocs(),
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
scaffoldMessengerKey: snackbarKey,
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: ThemeMode.light,
routeInformationParser: AppRoutes.routes().routeInformationParser,
routeInformationProvider: AppRoutes.routes().routeInformationProvider,
routerDelegate: AppRoutes.routes().routerDelegate,
);
}
}
router.dart
final navigatorKey = GlobalKey<NavigatorState>();
class AppRoutes {
static routes() {
return GoRouter(
navigatorKey: navigatorKey,
routes: <RouteBase>[
GoRoute(
path: "/",
pageBuilder: (BuildContext _, GoRouterState state) {
return CupertinoPage(
child: const MainScreen(),
key: state.pageKey,
restorationId: state.pageKey.value,
);
},
),
GoRoute(
path: "/welcome",
pageBuilder: (BuildContext _, GoRouterState state) {
return CupertinoPage(
child: const WelcomeScreen(),
key: state.pageKey,
restorationId: state.pageKey.value,
);
},
),
GoRoute(
name: "login",
path: "/login",
pageBuilder: (BuildContext _, GoRouterState state) {
return CupertinoPage(
child: const LoginScreen(),
key: state.pageKey,
restorationId: state.pageKey.value,
);
},
),
GoRoute(
path: "/signup",
pageBuilder: (BuildContext _, GoRouterState state) {
return CupertinoPage(
child: const SignupScreen(),
key: state.pageKey,
restorationId: state.pageKey.value,
);
},
),
GoRoute(
path: "/signup/verification",
pageBuilder: (BuildContext _, GoRouterState state) {
return CupertinoPage(
child: SignupVerificationScreen(
key: state.pageKey,
),
key: state.pageKey,
restorationId: state.pageKey.value,
);
},
),
GoRoute(
path: "/homepage",
pageBuilder: (BuildContext _, GoRouterState state) {
return CupertinoPage(
child: const MainTabScreen(),
key: state.pageKey,
restorationId: state.pageKey.value,
);
},
),
],
);
}
}
答案1
得分: 0
The problem is that calling AppRoutes.router()
creates a new GoRouter
instance every time you call it.
To fix, change this code:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
themeMode: ThemeMode.light,
/// Error: this creates a new GoRouter instance.
routeInformationParser: AppRoutes.routes().routeInformationParser,
/// Error: this creates a new GoRouter instance.
routeInformationProvider: AppRoutes.routes().routeInformationProvider,
/// Error: this creates a new GoRouter instance.
routerDelegate: AppRoutes.routes().routerDelegate,
);
}
}
To this code:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
themeMode: ThemeMode.light,
/// Automatically configures parser, provider, and delegate.
routerConfig: AppRoutes.routes(), // Use the same instance.
);
}
}
If for some reason you have to specify the three members, store the GoRouter
instance in a variable before assigning.
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
/// Create the router one time, and keep a reference.
final router = AppRoutes.routes();
return MaterialApp.router(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
themeMode: ThemeMode.light,
/// Now the same router instance is passed to parser, provider, and delegate.
routeInformationParser: router.routeInformationParser,
routeInformationProvider: router.routeInformationProvider,
routerDelegate: router.routerDelegate,
);
}
}
英文:
The problem is that calling AppRoutes.router()
creates a new GoRouter
instance every time you call it.
To fix, change this code:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
themeMode: ThemeMode.light,
/// Error: this creates a new GoRouter instance.
routeInformationParser: AppRoutes.routes().routeInformationParser,
/// Error: this creates a new GoRouter instance.
routeInformationProvider: AppRoutes.routes().routeInformationProvider,
/// Error: this creates a new GoRouter instance.
routerDelegate: AppRoutes.routes().routerDelegate,
);
}
}
To this code:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
themeMode: ThemeMode.light,
/// Automatically configures parser, provider, and delegate.
routerConfig: AppRoutes.routes(), // Use the same instance.
);
}
}
If for some reason you have to specify the three members, store the GoRouter
instance in a variable before assigning.
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
/// Create the router one time, and keep a reference.
final router = AppRoutes.routes();
return MaterialApp.router(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
themeMode: ThemeMode.light,
/// Now the same router instance is passed to parser, provider, and delegate.
routeInformationParser: router.routeInformationParser,
routeInformationProvider: router.routeInformationProvider,
routerDelegate: router.routerDelegate,
);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论