To read from one State to Another in flutter_bloc

Issue

I have been working on an app, here the basic structure looks like.
Having a MultiblocProvider. With two routes.

 Route generateRoute(RouteSettings routeSettings) {
    switch (routeSettings.name) {
      case BASE_ROUTE:
        return MaterialPageRoute(
          builder: (_) => BlocProvider(
            create: (context) => SignupCubit(),
            child: SignUp(),
          ),
        );
      case OTP_VERIFY:
        return MaterialPageRoute(
          builder: (_) => MultiBlocProvider(
            providers: [
              BlocProvider(
                create: (context) => VerifyCubit(),
              ),
              BlocProvider(
                create: (context) => SignupCubit(),
              ),
            ],
            child: Verify(),
          ),
        );
      default:
        return MaterialPageRoute(builder: (_) => Broken());
    }
  }

In OTP_Verify route I am giving access to two Cubit, VerifyCubit() and SignupCubit().

Now, what i am doing is,
There is two Screen, one is SignUp and the other is Verify. In SignUp Screen, if the state is SignUpSuccess, I am navigating to verify OTP screen.

 class SignUp extends StatelessWidget {
  const SignUp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    double deviceHeight = MediaQuery.of(context).size.height;

    return Scaffold(
      body: BlocListener<SignupCubit, SignupState>(
        listener: (context, state) {
          if (state is SignUpError) {
            showToast("Please try again");
          } else if (state is SignupSuccess) {
            print(state.email);
            Navigator.pushNamed(context, OTP_VERIFY); <--- Here
          } else if (state is EmailValidationError) {
            showToast("Not valid email");
          }
        },
        child: SafeArea(
          bottom: false,
          child: CustomScrollView(
            slivers: [
.... rest of code....

In VerifyOTP screen, i am trying to read state of current SignUpCubit

  ....other code....
 ElevatedButton(
              style: ElevatedButton.styleFrom(
                  minimumSize: const Size.fromHeight(45),
                  primary: Theme.of(context).primaryColor),
              onPressed: () {
                final signUpState = BlocProvider.of<SignupCubit>(context).state; <--- Here
                if (signUpState is SignupSuccess) {
                  print(signUpState.email);
                }
                BlocProvider.of<VerifyCubit>(context).setOtp(otp);
              },
              child: const Text('Verify'),
            ),
          .....other code.....

This is my SignUpState

    part of 'signup_cubit.dart';

@immutable
abstract class SignupState {}

class SignupIntial extends SignupState {}

class SignUpError extends SignupState {}

class SignupSuccess extends SignupState {
  final String email;

  SignupSuccess({required this.email});
}

class EmailValidationError extends SignupState {}

Now what I am assuming is I already emitted SignupSuccess in first page and I could read it in second page if I have provided that state by MultiBlocProvider.
But its not happening. Insted I am getting SignUpIntial.

Can someone please help, what i could be doing wrong, or is my method even valid ?

Solution

that’s because you provide a new instance of the SignupCubit while routing to Verify Screen. thus BlocProvider.of<SignupCubit>(context).state will return the state of the cubit above it which is still in the initial state.

I don’t know why you need to check the state of the SignupCubit in the Verify Since you only navigate to it when it’s SignupSuccess but anyway, a quick workaround is that you declare and initialize an instance of SignupCubit and use it in the provider around the SignUp and Verify Screens.

Answered By – omar hatem

Answer Checked By – Gilberto Lyons (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.