Unhandled Exception: BlocProvider.of() called with a context that does not contain a SignupBloc

Issue

I am a beginner in flutter_bloc library pattern, i am trying to signup http post request. I follow all the bloc necessary steps but when i click on Signup button it shows me on the log "Unhandled Exception:BlocProvider.of() called with a context that does not contain a SignupBloc. No ancestor could be found starting from the context that was passed to BlocProvider.of(). This can happen if the context you used comes from a widget above the BlocProvider." Although i have added this Signupbloc in main.dart how to fix this issue.

Main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MultiBlocProvider(providers: [
        BlocProvider<RecommendedBloc>(
          create: (BuildContext context) => RecommendedBloc(
            RecommendedForYouDataService(),
          ),
        ),
        BlocProvider<CuisineDishesBloc>(
          create: (BuildContext context) => CuisineDishesBloc(
            BrowseByCuisineDishesDataService(),
          ),
        ),
        BlocProvider<DetailsBloc>(
          create: (BuildContext context) => DetailsBloc(
            DetailsDataService(),
          ),
        ),
        BlocProvider<SearchBloc>(
          create: (BuildContext context) => SearchBloc(
              AllRestaurantDataService(), SearchRestaurantDataService()),
        ),
        BlocProvider<AllPhotosBloc>(
          create: (BuildContext context) =>
              AllPhotosBloc(AllPhotosDataService()),
        ),
        BlocProvider<PlacePhotosBloc>(
          create: (BuildContext context) =>
              PlacePhotosBloc(PlacePhotosDataService()),
        ),
        BlocProvider<FoodPhotosBloc>(
          create: (BuildContext context) =>
              FoodPhotosBloc(FoodPhotosDataService()),
        ),
        BlocProvider<EventPhotosBloc>(
          create: (BuildContext context) =>
              EventPhotosBloc(EventPhotosDataService()),
        ),
        BlocProvider<SignupBloc>(
          create: (BuildContext context) => SignupBloc(SignUpDataService()),
        ),
      ], child: LoginPage()),
    );
  }
}

SignUpDataService.dart

class SignUpDataService {
  Future<SignUp?> makeRequestSignUp(String firstName, String lastName,
      String mobileNumber, String password, String gender) async {
    var response =
        await http.post(Uri.parse('$baseURL/customer/signup'), body: {
      "phone_number": mobileNumber,
      "password": password,
    });
    if (response.statusCode == 200) {
      final responseString = response.body;
      final data = jsonDecode(responseString);
      SignUp signUp = SignUp.fromJson(data);
      return signUp;
    } else {
      throw Exception();
    }
  }
}

Signup_event.dart

@immutable
abstract class SignupEvent {}
class SignUpSubmittedEvent extends SignupEvent {
  final String phoneNumber;
  final String password;
  SignUpSubmittedEvent(this.firstName, this.lastName, this.phoneNumber,
      this.password, this.gender);
}

SignupState_state

@immutable
abstract class SignupState {}
class SignupInitialState extends SignupState {}
class SignupLoadingState extends SignupState {}
class SignupSuccessState extends SignupState {
  final SignUp data;
  SignupSuccessState(this.data);
}
class SignupErrorState extends SignupState {
  final String message;
  SignupErrorState(this.message);
}

Signup_bloc.dart

class SignupBloc extends Bloc<SignupEvent, SignupState> {
  SignUpDataService signUpDataService;
  SignupBloc(this.signUpDataService) : super(SignupInitialState());
  @override
  Stream<SignupState> mapEventToState(
    SignupEvent event,
  ) async* {
    if (event is SignUpSubmittedEvent) {
      yield SignupLoadingState();
      try {
        SignUp? signup = await signUpDataService.makeRequestSignUp(
            event.phoneNumber,
            event.password,
        yield SignupSuccessState(signup!);
      } catch (e) {
        yield SignupErrorState(e.toString());}}}}

Register.dart

class RegisterPage extends StatefulWidget {
  const RegisterPage({Key? key}) : super(key: key);

  @override
  _RegisterPageState createState() => _RegisterPageState();
}

class _RegisterPageState extends State<RegisterPage> {
  bool checkOS = Platform.isIOS;
  late bool _passwordVisible;
  final TextEditingController mobileNumber = TextEditingController();
  final TextEditingController password = TextEditingController();
  bool _validate = false;
  final _formKey = GlobalKey<FormState>();
  String pWord = "";
  late List<String> menus;
  static late int menuIndex;
  late SignupBloc signupBloc;

  void submitForm() {
    final isValid = _formKey.currentState!.validate();
  }

  @override
  void initState() {
    _passwordVisible = false;
    super.initState();
  }


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

    return Scaffold(
      backgroundColor: TuxedoColor.loginColor,
      body: Padding(
        padding: const EdgeInsets.only(left: 20.0, right: 20.0),
        child: Container(
          alignment: Alignment.center,
          child: Center(
            child: Form(
              key: _formKey,
              child: SingleChildScrollView(
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          GestureDetector(
                            onTap: () {
                              Navigator.pop(context);
                            },
                            child: Container(
                              decoration: BoxDecoration(
                                border:
                                    Border.all(color: TuxedoColor.greyColor),
                                borderRadius: BorderRadius.all(Radius.circular(
                                        5.0) //                 <--- border radius here
                                    ),
                              ),
                              child: Padding(
                                padding: const EdgeInsets.only(
                                    top: 10.0,
                                    bottom: 10.0,
                                    left: 10.0,
                                    right: 5.0),
                                child: Icon(
                                  Icons.arrow_back_ios,
                                  color: TuxedoColor.greyColor,
                                ),
                              ),
                            ),
                          ),
                          Text(
                            'Sign Up',
                            style: TextStyle(
                                fontSize: 25.0, fontWeight: FontWeight.bold),
                          ),
                          GestureDetector(
                            onTap: () {},
                            child: Text(
                              'عربي',
                              style: TextStyle(
                                  fontSize: 20.0, fontWeight: FontWeight.bold),
                            ),
                          )
                        ],
                      ),
                    ),
                   
                    Padding(
                      padding: const EdgeInsets.only(
                          left: 15.0, right: 15.0, top: 35.0),
                      child: TextFormField(
                        controller: mobileNumber,
                        keyboardType: TextInputType.phone,
                        decoration: new InputDecoration(
                          fillColor: TuxedoColor.textFieldColor,
                          filled: true,
                          hintText: "Mobile Number",
                          enabledBorder: OutlineInputBorder(
                              borderSide:
                                  BorderSide(color: TuxedoColor.greyColor)),
                          focusedBorder: OutlineInputBorder(
                              borderSide:
                                  BorderSide(color: TuxedoColor.greyColor)),
                        ),
                        
                      ),
                    ),
                    
                    Padding(
                      padding: const EdgeInsets.only(
                          left: 15.0, right: 15.0, top: 30.0),
                      child: TextFormField(
                        keyboardType: TextInputType.visiblePassword,
                        controller: password,
                        obscureText: !_passwordVisible,
                       
                        onChanged: (value) => pWord = value,
                        decoration: new InputDecoration(
                            suffixIcon: IconButton(
                              icon: Icon(
                                _passwordVisible
                                    ? Icons.visibility
                                    : Icons.visibility_off,
                              ),
                              onPressed: () {
                                setState(() {
                                  _passwordVisible = !_passwordVisible;
                                });
                              },
                            ),
                            fillColor: TuxedoColor.textFieldColor,
                            filled: true,
                            hintText: "Password",
                            enabledBorder: OutlineInputBorder(
                                borderSide:
                                    BorderSide(color: TuxedoColor.greyColor)),
                            focusedBorder: OutlineInputBorder(
                                borderSide:
                                    BorderSide(color: TuxedoColor.greyColor))),
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.only(
                        left: 15.0,
                        right: 15.0,
                      ),
                      child: ConstrainedBox(
                        constraints:
                            BoxConstraints.tightFor(height: height * 0.065),
                        child: ElevatedButton(
                            style: ButtonStyle(
                              backgroundColor: MaterialStateProperty.all(
                                  TuxedoColor.redColor),
                            ),
                            onPressed: () async {
                              submitForm();
                              final fName = firstName.text;
                              final lName = lastName.text;
                              final mNumber = mobileNumber.text;
                              final pass = password.text;
                              final gen = gender.toString();
                              signupBloc = BlocProvider.of<SignupBloc>(context)
                                ..add(SignUpSubmittedEvent(
                                    mNumber, pass)); //On this line getting error
                            },
                            child: Text(
                              'SignUp',
                              style: TextStyle(
                                  fontWeight: FontWeight.bold,
                                  fontSize: 18.0,
                                  color: TuxedoColor.blackColor),
                            )),
                      ),
                    ),
                    
                        ],
                      ),
                    )
                  ],
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Solution

You should swap MaterialApp and MultiBlocProvider.

Bloc provider must be on top of MaterialApp as suggested in this issue by lib creator Felix.

Answered By – Emir Bostancı

Answer Checked By – Clifford M. (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *