context.go("/home") not working inside listener of BlocConsumer()

huangapple go评论62阅读模式
英文:

context.go("/home") not working inside listener of BlocConsumer()

问题

为什么在 BlocListener 或 BlocConsumer 内部使用 context.go("/routeName") 在注册页面不起作用?

我目前正在使用 flutter_blocgo_router。 在注册页面,一旦用户提交了详细信息,我会向后端发送请求。 一旦我从后端获取到令牌,我会发出 SignupSuccessfulState,并在注册屏幕中使用 BlocConsumer。 当状态为 SignupSuccessfulState 时,我想将用户发送到另一页并删除所有先前的路由。 因此,在 BlocConsumer 的监听器中,我添加了 context.go("/homepage")。 但是 context.go("") 在监听器内部不起作用,而 context.pop()context.push() 等选项都能正常工作。我正在使用 go_router: ^7.0.0flutter_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,
    );
  }
}

huangapple
  • 本文由 发表于 2023年5月24日 21:41:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76324194.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定